Reputation: 8819
I have a bunch of records (A B C) that implement a protocol P.
I want to write a method which will select one of the types of records, construct it, and then call a method on it.
For example, if I have a list of the records
(def types '(A B C))
I want to do something like (->(first types) 1 2 3)
Upvotes: 3
Views: 82
Reputation: 3014
Well, functions are also values and can be stored in and retrieved from data structures. So you should be able to just store the constructor functions you want to pick from in some convenient format and use them from there. Something like:
(defrecord foo [x y])
(defrecord bar [x y z])
(def constructors [->foo ->bar])
((first constructors) 4 5) ;;=> #user.foo{:x 4, :y 5}
;;or
(apply (second constructors) [20 true :baz]) ;;=> #user.bar{:x 20, :y true, :z :baz}
(-> (second constructors) (apply '(59 -30 false))) ;;=> #user.bar{:x 59, :y -30, :z false}
or you can even skip the data structure entirely:
(defn quxx [n a-map]
((if (< 25 n) map->foo map->bar) a-map))
(quxx 2 {:x 3 :y 9 :z -200}) ;;=> #user.bar{:x 3, :y 9, :z -200}
(quxx 29 {:x 3 :y 9 :z -200}) ;;=> #user.foo{:x 3, :y 9, :z -200}
Upvotes: 1