Paul C
Paul C

Reputation: 8457

if 'x evaluates to (var x) in clojure, why aren't they equal?

In the O'Reilly "Clojure Programming: Practical Lisp for the Java World", there is a statement:

The var special form does this:

(def x 5)
(var x) 
;= #' user/x 

You’ve seen a number of times now how vars are printed in the REPL: #', followed by a symbol. This is reader syntax that expands to a call to var:

 #'x 
 ;= #' user/x

(Kindle Locations 1278-1282).

Testing this out doesn't seem to be the case. I would think the type types would be the same.

[user]> (def x 5)
#'user/x

[user]> (= 'x (var x))
false

[user]> (type 'x)
#<Class@c540f5a clojure.lang.Symbol>

[user]> (type (var x))
#<Class@77e9807f clojure.lang.Var>

[user]> 'x
x

[user]> (var x)
#'user/x

Upvotes: 0

Views: 72

Answers (1)

Alan Thompson
Alan Thompson

Reputation: 29958

You are missing the # symbol:

(def x 5)
(spyx (var x))
(spyx #'x)

(var x) => #'tst.clj.core/x
(var x) => #'tst.clj.core/x

The clojure reader consumes the charcters in your source file, and does a substitution of #'x => (var x) before it even gets to the compiler. As you can see above, the spyx macro ("spy expression") doesn't even see the original #'x expression - the substitution has already occurred.

Thus we get:

(= #'x (var x)) => true

You can also try:

(println "type 1:  " (type (var x)))
(println "type 2:  " (type #'x))

;=> type 1:   clojure.lang.Var
;=> type 2:   clojure.lang.Var

If you wish to play with the spy, spyx, or spyxx macros, you will need to add this to your project.clj:

   [tupelo "0.9.19"]

Upvotes: 5

Related Questions