odd failure on recursive use of protocol member

2013-12-10 Thread Michael Blume
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!

-- 
-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: odd failure on recursive use of protocol member

2013-12-10 Thread Kevin Downey
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


Re: odd failure on recursive use of protocol member

2013-12-10 Thread Michael Blume
Oh, interesting. I knew it was changing *some* state but I didn't realize
it was actually changing the binding of the rest-serialize var.  Thanks =)


On Tue, Dec 10, 2013 at 4:09 PM, Kevin Downey redc...@gmail.com wrote:

 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?



-- 
-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.