1

Short Version

I want a multi-arity function to dispatch on type for the 2-arity version, but I want the 1-arity version identical across all types.

Long Version (With Example)

I have a protocol that looks something like this

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

If I want "TypeA" to extend this protocol, then I have the following

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

for some function TypeA-fn specific to TypeA.

If I want "TypeB" to extend this protocol then I have the following

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

for some function TypeB-fn specific to TypeB.

The effect that I am trying to create is that of currying.

(bar instance-of-TypeA x)

is a double, say, whilst

(bar instance-of-TypeA)

returns a function that maps TypeA to a double.

The point is that the single arity implementation of bar is always the same, whilst the multiple arity implementation depends on the type. Naturally I don't want to repeat myself every time I extend this protocol for the single-arity version, so what is the idiomatic clojure way to do this. I have considered not specifying a single arity version, and using (partial bar TypeX) everywhere, but I grow tired of partial.

proposed solution I could wrap the original function inside a new function, for example

(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))

but the introduction of two functions for the purpose of one seems inelegant.

Lindon
  • 1,292
  • 1
  • 10
  • 21

1 Answers1

2

Your proposed solution is exactly what I would suggest. You want a function of one or two arguments; in the two-argument case you want it to be polymorphic, so it makes sense for that case to forward to something that does polymorphic dispatch.

amalloy
  • 89,153
  • 8
  • 140
  • 205