Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reuse deftype methods in Clojure / Clojurescript?

I'm trying to extend library DomKM/silk.

Specifically there's deftype Route which implements protocol Pattern, which has method implementations, which I'd like to reuse in my custom implementation of Pattern protocol.

https://github.com/DomKM/silk/blob/master/src/domkm/silk.cljx#L355

(deftype Route [name pattern]
  Pattern
  (-match [this -url]
          (when-let [params (match pattern (url -url))]
            (assoc params ::name name ::pattern pattern)))
  (-unmatch [this params]
            (->> (dissoc params ::name ::pattern)
                 (unmatch pattern)
                 url))
  (-match-validator [_]
                    map?)
  (-unmatch-validators [_]
                       {}))

Ok so my implementation would look somehow like this, but I'd like to "inherit" Route's methods. I mean execute some custom logic first and then pass it to original Route methods.

(deftype MyRoute [name pattern]
  silk/Pattern
  (-match [this -url] 
    true) ;match logic here
  (-unmatch [this {nm ::name :as params}]
    true) ;unmatch logic here
  (-match-validator [_] map?)
  (-unmatch-validators [_] {}))

How is this done in clojure / clojurescript?

like image 338
ma2s Avatar asked Aug 23 '15 20:08

ma2s


1 Answers

There's no need to redef the type. Referring to "ancestor" protocol implementation is possible, from another namespace.

user=> (ns ns1)
nil
ns1=> (defprotocol P (f [o]))
P
ns1=> (deftype T [] P (f [_] 1))
ns1.T
ns1=> (f (T.))
1
ns1=> (ns ns2)
nil
ns2=> (defprotocol P (f [o]))
P
ns2=> (extend-protocol P ns1.T (f [o] (+ 1 (ns1/f o))))
nil
ns2=> (f (ns1.T.))
2

Keep in mind that ns1.P and ns2.P are totally different cats, both called P.

like image 168
François De Serres Avatar answered Nov 04 '22 09:11

François De Serres