2024年Clojure状态调查!中分享您的想法。

欢迎!请访问关于页面以获取更多有关如何操作的信息。

0
协议

实现arity-overloaded协议方法所需的形式在 "extend-**" 宏和 "defrecord" 之间不一致。

"extend" 宏系列要求重载方法定义遵循 defn 使用的形式

(method ([arg1] ...) ([arg1 arg2] ...))

但是,“defrecord”要求将实现分别定义

(method [arg1] ...) (method [arg1 arg2] ...)

此外,如果定义错误,错误模式也没有帮助。

如果您使用“defrecord”形式与“extend-**”,它将成功评估,但稍后定义将静默覆盖先前定义。

如果您使用“extend-**”形式与“defrecord”,它将在方法体上给出关于“不受支持的绑定形式”的晦涩错误。

这与CLJ-1056问题不同:这与声明协议的语法有关,而这个问题是关于实现协议的语法。

`

(defprotocol MyProtocol
(mymethod

[this arg]
[this arg optional-arg]))

(extend-protocol MyProtocol
Object
(mymethod

([this arg] :one-arg)
([this arg optional-arg] :two-args)))

;; BAD! 由于 "Unsupported binding form: :one-arg" 而崩溃
(defrecord MyRecord []
MyProtocol
(mymethod

([this arg] :one-arg)
([this arg optional-arg] :two-args)))

;; Works...
(defrecord MyRecord []
MyProtocol
(mymethod [this arg] :one-arg)
(mymethod [this arg optional-arg] :two-args))

;; Evals...
(extend-protocol MyProtocol
Object
(mymethod [this arg] :one-arg)
(mymethod [this arg optional-arg] :two-args))

;; 但然后... 错误! "参数数量不正确"
(mymethod :obj :arg)

;; 2-arg版本可以调用...
(mymethod :obj :arg1 :arg2)
`

4 答案

0
_由pparkkin发送的评论:

附上了修复此问题的补丁。

对于 defrecord,我检查用于定义方法的样式,并如果使用了新样式,则将其转换为原始样式。对于检查,我做的是我认为 defn 会做的,即 {{(vector? (first fdecl))}}。

对于 extend-*,我跳过检查,将一切转换为相同的格式。

为两者都包括测试。

所有测试通过。
0
by

由 richhickey 发布的评论:

提案是什么?

0
by
评论由:tsachev_ 发布

这也让我感到困惑。

我使用 {{extend}} 在具有多参数方法的协议中作为解决方案
即在上面的示例中

(extend Object
  MyProtocol
  {:mymethod (fn ([^Object this arg] :one-arg)
                 ([^Object this arg optional-arg] :two-args))})
0
by
参考: https://clojure.atlassian.net/browse/CLJ-825 (由 alex+import 报告)
...