我有一个函数foo
,它接受一个参数,其实现取决于参数的类型,因此是一个协议:
(defprotocol Foo
(foo [x]))
在同一名称空间中,我还想要一个具有相同名称(foo
)的函数,该函数接受变量参数,并且每个参数都调用单参数foo
。类似的东西:
(defn foo [x1 x2 & more]
(doseq [x (concat [x1 x2] more)])
(foo x))))
如何实现?
答案 0 :(得分:2)
使用defprotocol
您已声明函数foo
。稍后调用(defn foo ...)
会有效地覆盖您之前的声明。
一个常见的习惯用法是在你的协议fn(即-
)前加-foo
。这基本上是匈牙利语符号“这是一个内部协议函数。在这个命名空间中有一个包装器。你应该调用它。”这使协议保持打开以进行扩展,但允许您包装调用。
我要考虑的另一件事是名称foo
是否适合您的包装器。它在多个Foo
上运行的事实表明,do-foos
之类的东西更合适。
答案 1 :(得分:2)
只需添加Tim Pote的答案,我就引用answer from Stuart Halloway:
协议是实施者的合同,而不是呼叫者的合同。如果您更改了实施者的合同,那么实施者必须更改。[...]具有任何对象的合理默认值的函数。通常,这样的功能根本不需要成为实施者(即协议)合同的一部分。
协议实现者正在解放,因为你可以在公共api fn中设置默认值或为多个arities添加支持(如你的情况),而不必担心具体实现中的所有这些。