【问题标题】:how to combine protocol function with function with same name and different arity?如何将协议功能与具有相同名称和不同数量的功能结合起来?
【发布时间】:2015-09-08 17:13:12
【问题描述】:

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

(defprotocol Foo
  (foo [x]))

在同一个命名空间上,我还想要一个具有相同名称 (foo) 的函数,它接受可变参数并为每个参数调用单参数 foo。比如:

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

如何实现?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    只是添加蒂姆波特的答案,让我引用answer from Stuart Halloway

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

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

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

    【讨论】:

    • 这个电子邮件线程很棒。谢谢你把这个扔进去。
    • 哦,是“另一个”斯图尔特。感谢您的修复:)
    【解决方案2】:

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

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

    在您的情况下,我会考虑的另一件事是名称 foo 是否适合您的包装器。它在多个Foos 上运行的事实表明,也许像do-foos 这样的东西更合适。

    【讨论】:

      猜你喜欢
      • 2016-05-03
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多