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

欢迎!有关如何工作的更多信息,请查看关于页面。

0
协议

实现重载算子数协议方法的所需形式在“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}} 来解决这个问题,对于具有多个arity方法的协议
例如,对于上面的例子

(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 报告)
...