In Clojure,
(def x 3)
(eval '(prn x))
prints 3, whereas
(let [y 3]
(eval '(prn y)))
and
(binding [z 3] (eval '(prn z)))
generate an ‘Unable to resolve var’ exception.
According to http://clojure.org/evaluation, eval, load-string, etc generate temporary namespaces to evaluate their contents. Therefore, I’d expect neither of the above code samples to work, since (def x 3) is done in my current namespace, not the one created by eval.
- Why does the first code sample work and not the last two?
- How can I
evala form with bound variables without usingdef?
Thanks!
1.:
The reason this doesn’t work is (more or less) given on the page you linked:
And:
evalevaluates forms in an empty (null in CL-lingo) lexical environment. This means, that you cannot access lexical variable bindings from the caller’s scope. Also,bindingcreates new bindings for existing vars, which is why you cannot use it “by itself”, without havingdeclared ordefed the variables you try to bind. Besides, lexical variables (at least in CL, but I would be surprised if this wasn’t the case for Clojure) already ceased to exist at runtime – They are translated to addresses or values.See also my older post about this topic.
2.:
So, you have to use dynamic variables. You can avoid the explicit
def, but you still at least need todeclarethem (whichdefs var names without bindings):By the way: I suppose you know why you need eval, and that its use is considered evil when other solutions would be appropriate.