extend mutates some state (the protocol definition), so what is happen here is comp is returning a new function built from the value of the rest-serialize var (the protocol function before the extend changes it) and the value of the deref var.
I have not verified this, but I suspect if you use (fn [x] (rest-serialize (deref x))) instead of the comp version, you will get the behaviour you expected On 12/10/13, 11:50 AM, Michael Blume wrote: > I have a protocol RestSerializable to represent data that can be serialized > to json from a REST interface. > > (defprotocol RestSerializable > (rest-serialize [this] > "Convert to something Cheshire can JSONify")) > > By default, things are left alone > > (extend Object > RestSerializable > {:rest-serialize identity}) > > But I want atoms and the like to be transparent when serialized > > (extend clojure.lang.IDeref > RestSerializable > {:rest-serialize (comp rest-serialize deref)}) > > I would expect this to mean that, say, > > (-> 42 atom atom atom atom rest-serialize) > > would just unwrap to 42, but in fact it only unwraps the outer atom and > leaves the inner ones alone. > > Here's where it gets weird though. If I just evaluate the extend > clojure.lang.IDeref form again, rest-serialize suddenly gains the ability > to unwrap *two* layers of atoms. Eval it again and it can unwrap *three*. > Kinda feels like the exercises in Little Schemer when they're building up > to the Y Combinator. > > Here's my REPL session demonstrating this (not shown, but I've verified > this behavior is the same in Clojure 1.5.1 and Clojure 1.6.0-alpha3) > > $ lein repl > nREPL server started on port 46049 on host 127.0.0.1 > REPL-y 0.2.1 > Clojure 1.5.1 > Docs: (doc function-name-here) > (find-doc "part-of-name-here") > Source: (source function-name-here) > Javadoc: (javadoc java-object-or-class-here) > Exit: Control+D or (exit) or (quit) > Results: Stored in vars *1, *2, *3, an exception in *e > > user=> (defprotocol RestSerializable > #_=> (rest-serialize [this] > #_=> "Convert to something Cheshire can JSONify")) > RestSerializable > user=> > > user=> (extend Object > #_=> RestSerializable > #_=> {:rest-serialize identity}) > nil > user=> > > user=> (extend clojure.lang.IDeref > #_=> RestSerializable > #_=> {:rest-serialize (comp rest-serialize deref)}) > nil > user=> (-> 7 atom atom atom rest-serialize) > #<Atom@56153406: #<Atom@a0aa211: 7>> > user=> (-> 7 atom atom atom rest-serialize) > #<Atom@3c19a5b0: #<Atom@37cce4a3: 7>> > user=> (-> 7 atom atom atom rest-serialize) > #<Atom@9f6e629: #<Atom@308092db: 7>> > user=> (extend clojure.lang.IDeref > #_=> RestSerializable > #_=> {:rest-serialize (comp rest-serialize deref)}) > nil > user=> (-> 7 atom atom atom rest-serialize) > #<Atom@7fb48906: 7> > user=> (-> 7 atom atom atom rest-serialize) > #<Atom@41e224a5: 7> > user=> (extend clojure.lang.IDeref > #_=> RestSerializable > #_=> {:rest-serialize (comp rest-serialize deref)}) > nil > user=> (-> 7 atom atom atom rest-serialize) > 7 > user=> (quit) > Bye for now! > -- And what is good, Phaedrus, And what is not good— Need we ask anyone to tell us these things?
signature.asc
Description: OpenPGP digital signature