Clojure协议 - 仅在2-arity版本的多重功能

时间:2017-04-27 00:56:35

标签: clojure clojurescript arity

短版

我希望多个arity函数为2-arity版本的类型分派,但我希望所有类型的1-arity版本相同。

长版(带示例)

我有一个看起来像这样的协议

(defprotocol foo
  (bar [d] [d x]))

如果我想要" TypeA"为了扩展这个协议,我有以下

(extend-protocol foo
  TypeA
  (bar
    ([d] #(bar d %))
    ([d x] (TypeA-fn x))))

对于某些特定于TypeA的函数TypeA-fn。

如果我想要" TypeB"为了扩展这个协议,我有以下

(extend-protocol foo
  TypeB
  (bar
    ([d] #(bar d %))
    ([d x] (TypeB-fn x))))

对于某些特定于TypeB的函数TypeB-fn。

我试图创造的效果就是currying。

(bar instance-of-TypeA x)

是双重的,比如,

(bar instance-of-TypeA)

返回一个将TypeA映射为double的函数。

关键是bar的单个arity实现总是相同的,而多个arity实现取决于类型。当然,每次我为单一版本扩展此协议时,我都不想重复自己,那么这个惯用的clojure方法是什么呢?我考虑过不指定单个arity版本,并且在任何地方都使用(部分条形TypeX),但我厌倦了局部。

建议的解决方案 我可以将原始函数包装在一个新函数中,例如

(defprotocol foo
  (bar-method [d x]))

(extend-protocol foo
  TypeA
  (bar-method
    ([d x] (TypeA-fn x))))

(defn bar
([d] (fn [x] (bar-method d x))
([d x] (bar-method d x))

但为了一个目的而引入两个功能似乎不够优雅。

1 个答案:

答案 0 :(得分:1)

您建议的解决方案正是我所建议的。你想要一个或两个参数的函数;在两个参数的情况下,你希望它是多态的,所以这种情况转发到多态调度的东西是有道理的。