Clojure 如何将协议函数与同名异数函数结合起来?

Clojure 如何将协议函数与同名异数函数结合起来?,clojure,Clojure,我有一个函数foo,它接受一个参数,该参数的实现取决于参数的类型,因此有一个协议: (defprotocol Foo (foo [x])) 在同一名称空间中,我还想要一个具有相同名称(foo)的函数,该函数接受变量参数,并为每个参数调用单个argfoo。比如: (defn foo [x1 x2 & more] (doseq [x (concat [x1 x2] more)]) (foo x)))) 如何实现它?使用defprotocol您已经声明了函数foo。稍后调用

我有一个函数
foo
,它接受一个参数,该参数的实现取决于参数的类型,因此有一个协议:

(defprotocol Foo
  (foo [x]))
在同一名称空间中,我还想要一个具有相同名称(
foo
)的函数,该函数接受变量参数,并为每个参数调用单个arg
foo
。比如:

(defn foo [x1 x2 & more]
  (doseq [x (concat [x1 x2] more)])
    (foo x))))

如何实现它?

使用
defprotocol
您已经声明了函数
foo
。稍后调用
(defn foo…
会有效地覆盖以前的声明

一种常见的习惯用法是在协议fn前面加上
-
(即
-foo
)。这基本上是匈牙利符号,表示“这是一个内部协议函数。在这个名称空间中有一个它的包装器。你应该调用它。”这使协议可以扩展,但允许你包装调用


<> P>我在您的案例中考虑的另一个问题是,名称<代码> FoO 是否适合您的包装器。它在多个
Foo
s上运行的事实表明,像
dofoos
这样的东西可能更合适。

使用
deprotocol
您已经声明了函数
Foo
。稍后调用
(defn foo…
会有效地覆盖以前的声明

一种常见的习惯用法是在协议fn前面加上
-
(即
-foo
)。这基本上是匈牙利符号,表示“这是一个内部协议函数。在这个名称空间中有一个它的包装器。你应该调用它。”这使协议可以扩展,但允许你包装调用


<> P>我在您的案例中考虑的另一个问题是,名称<代码> FoO 是否适合您的包装器。它在多个
Foo
s上运行的事实表明,像
do foos
这样的东西可能更合适。

只是补充Tim Pote的答案,让我引用一个:

[…]协议是实现者的契约,而不是调用者的契约。如果您更改了实现者的合同,那么实现者必须更改

[…]对任何对象都有合理默认值的函数。通常,这种功能根本不需要成为实现者合同(即协议)的一部分


这对协议实现者来说是一种解放,因为您可以在公共api fn中设置默认值或添加对多个算术的支持(就像您的例子一样),而不必在具体实现中担心所有这些。

仅在Tim Pote的回答中添加一点,让我引用一句:

[…]协议是实现者的契约,而不是调用者的契约。如果您更改了实现者的合同,那么实现者必须更改

[…]对任何对象都有合理默认值的函数。通常,这种功能根本不需要成为实现者合同(即协议)的一部分


这对协议实现者来说是一种解放,因为您可以在公共api fn中设置默认值或添加对多个算术的支持(就像您的例子一样),而不必在具体实现中担心所有这些。

Man电子邮件线程太棒了。谢谢你把这个扔进去。哦,是“另一个”斯图尔特。谢谢你的修复:)老兄,这封邮件太棒了。谢谢你把这个扔进去。哦,是“另一个”斯图尔特。感谢修复:)