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?

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to