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)))

;; 错误!崩溃:"不支持的绑定形式::one-arg"
(defrecord MyRecord []
MyProtocol
(mymethod

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

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

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

;; 但然后... 错误!"参数数量不正确"
(mymethod :obj :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 reported)
...