Ben Kovitz
Ben Kovitz

Reputation: 5030

How to forward protocol methods to existing type?

How can I define a new record that "inherits" the protocols from an existing type?

To make this question clear, I'll illustrate with extending Ubergraph, but Ubergraph is only an example; I'm looking for the general solution, not just a solution that works for Ubergraph. Suppose that I'd like to add a global attribute, graph-name, to Ubergraph. Ideally, I could do something like this:

(defrecord named-ubergraph [g graph-name])

(extend-type named-ubergraph
  (all-the-protocols-supported-by ubergraph.core.Ubergraph)
  (call-the-same-functions-replacing-first-argument-with '(this g))

Of course I could look at the Ubergraph source code and manually write all the forwarding functions, but as you can see here, Ubergraph satisfies many protocols and many protocol methods.

Writing so much boilerplate code doesn't sound very Clojurely, and it seems like a lot of work when all I want to do is add one eensy-weensy bit of data to an Ubergraph. What's a better way?

Please feel free to reconceptualize the question if you think I'm looking at this wrong.

Upvotes: 2

Views: 128

Answers (1)

Juraj Martinka
Juraj Martinka

Reputation: 4366

extend-type extends existing types to given protocols. If I understand you properly, you want to extend existing record to achieve some kind of inheritance. AFAIK, there's no easy way to do this. However, if all you want is to add another field, you can easily assoc additional field to an existing record instance:

(defprotocol Cost
  (cost [this price-list]))

(defrecord Car [name speed]
  Cost
  (cost [this price-list] (price-list (:name this))))

(def my-car (->Car "bmw" 200))
(def price-list {"bmw" 100000})

(cost my-car price-list)
;;=> 100000

(-> my-car
    (assoc :color "blue")
    (cost price-list))
;;=> 100000

UPDATE: I've also found this fantastic discussion on Clojure mailing list: defrecord with "inheritance": https://groups.google.com/forum/#!topic/clojure/mr-o9sRyiZ0

Upvotes: 1

Related Questions