Hi,

I have discovered strange difference between methods implemented directly 
in defrecord and methods added later using extend (extend-type).

I simplified the issue to code example listed bellow. Both records FooRec 
and BarRec implement simple protocol FooProto with method foo. There is 
also evil function transmogrify, which takes a function F and returns new 
function which calls F. I use transmogrify to produce function foo*

If you call foo method directly, everything works as expected. When you 
call foo*, FooRec method is OK, but BarRec fails with following exception

No implementation of method: :foo of protocol: #'user/FooProto found for 
class: user.BarRec


Which looks weird because you can call foo directly... 

I expect that defrecord and extend use different approach to extending the 
type and foo* ends up with a reference to old version of protocol. 
`defrecord` somehow manages to modify directly the protocol definition 
referenced by foo*, while `extend` takes more immutable approach and 
replaces old protocol definition (which foo* cannot see). I briefly dived 
into Clojure sources and found that indeed `extend` ends with some sort of 
alter-root-var, while `defrecord` traces ends deep in java sources 
(deftype*).

It would be good idea to unify defrecord and extend so they have same 
behaviour.

Dan

(defprotocol FooProto
  (foo [X Y] "Make a foo"))

(defn transmogrify [F Y]
  (fn [A] (F A Y)))

(def foo* (transmogrify foo "Bar"))

(defrecord FooRec []
  FooProto
  (foo [X Y] (println "Hello," Y)))

(foo (FooRec.) "World")
; -> Hello, World

(foo* (FooRec.))
; -> Hello, Bar

(defrecord BarRec [])

(extend-type BarRec
  FooProto
  (foo [X Y] (println "Bar" Y)))

(foo (BarRec.) "Bar")
; -> Bar Bar

(foo* (BarRec.))
; bang!

; No implementation of method: :foo of protocol: #'user/FooProto found for 
class: user.BarRec 

 

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to