Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure: resolve declares symbol

I get some weird behaviour when checking if a symbol can be resolved.

user=> ok
CompilerException java.lang.RuntimeException: Unable to resolve symbol: ok in this context, compiling:(NO_SOURCE_PATH:0)
user=> (resolve 'ok)
nil
user=> (if (resolve 'ok) "bla" (def ok 'ok))
"bla"
user=> ok
#<Unbound Unbound: #'user/ok>
user=> (def ok 'ok)
#'user/ok
user=> ok
ok

Can anyone tell me where this might come from? Is this behaviour intended?

like image 376
Dominik G Avatar asked Jan 14 '12 12:01

Dominik G


2 Answers

(def ok "whatever") creates a variable named ok at compile time. The compiler scans the whole form to compile it, discovers that you will be defining a var named ok, and creates it for you (with no binding), before your form is actually executed. When the def form is actually executed, the runtime value of the expression will be assigned to the var user/ok. In your example, this never happens, because the var has already been created, and the if branch goes the other way.

Using bound? as a substitute is a terrible idea, as it tests something quite different: whether the named var (which must exist) has a binding, either permanent or thread-local.

like image 84
amalloy Avatar answered Oct 22 '22 07:10

amalloy


Since I only use it inside a macro I now use it as follows

(defmacro bla [x]
    (if (resolve x) x `(def ~x '~x)))

And now it works since def is inside the quoted form and evaluated after resolve.

like image 45
Dominik G Avatar answered Oct 22 '22 06:10

Dominik G