简体   繁体   English

如何将协议功能与具有相同名称和不同属性的功能相结合?

[英]how to combine protocol function with function with same name and different arity?

I have a function foo that takes a single argument whose implementation depends on the type of the argument, hence a protocol: 我有一个函数foo ,它接受一个参数,其实现取决于参数的类型,因此是一个协议:

(defprotocol Foo
  (foo [x]))

On the same namespace, I also would like a function with the same name ( foo ) that takes variable arguments and that calls for each argument the single-arg foo . 在同一个名称空间上,我还想要一个具有相同名称( foo )的函数,该函数接受可变参数,并为每个参数调用single-arg foo Something like: 就像是:

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

How to implement that? 如何实施?

With the defprotocol you've declared the function foo . 使用defprotocol您已经声明了foo函数。 Later calling (defn foo ...) effectively overwrites your previous declaration. 以后调用(defn foo ...)有效地覆盖了您之前的声明。

One common idiom is to prepend a - to your protocol fn (ie -foo ). 一种常见的习惯用法是在协议fn之前加一个- (即-foo )。 This is basically Hungarian Notation for "This is an internal protocol function. There is a wrapper for it in this namespace. You should call that instead." 这基本上是匈牙利符号,表示“这是一个内部协议功能。在该名称空间中有一个包装器。您应该调用它。” This leaves the protocol open for extension, but allows you to wrap the invocation. 这使协议可以扩展,但是允许您包装调用。

Another thing I would consider in your case is whether or not the name foo is appropriate for your wrapper. 在您的情况下,我还要考虑的另一件事是名称foo是否适合您的包装器。 The fact that it operates on multiple Foo s indicates that maybe something like do-foos is more appropriate. 它在多个Foo上运行的事实表明,也许像do-foos更合适。

Just adding to Tim Pote's answer, let me quote an answer from Stuart Halloway : 我只是在补充Tim Pote的答案,然后引用Stuart Halloway答案

[...] protocols are the contract for implementers, not the contract for callers. 协议是实施者的合同,而不是呼叫者的合同。 If you change a contract for implementers, then the implementers must change. 如果您更改实施者的合同,则实施者必须更改。

[...] a function that has a reasonable default for any object. [...]对任何对象都有合理默认值的函数。 Often such a function does not need to be part of the contract for implementers (ie the protocol) at all. 通常,此类功能根本不需要成为实施者合同(即协议)的一部分。

It's liberating for the protocol implementers, because you can set default values or add support to multiple arities (like in your case) in the public api fn, without having to worry about all of that in the concrete implementations. 对于协议实现者而言,这是一种解放,因为您可以在公共api中设置默认值或添加对多个Arity的支持(例如您的情况),而不必担心具体实现中的所有问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM