According to spec, def
should intern the var in the current ns (i.e. *ns*). However, the following code does not look anything like it:
(ns namespace-b)
(defn def_something []
(ns namespace-a)
(println *ns*) ;prints namespace-a as it should
(def something 1)
)
(def_something)
(println namespace-b/something) ; prints 1
(println namespace-a/something) ; throws
What am I missing?
Notes:
defn
is used just for clarity. Defining and running anonymous function works just as well.def
inside function is probably not very idiomatic. However, this is just extracted essence of a bigger problem I ran into.The parser already interns the var to the current namespace at compile time, although it won't be bound immediately:
(defn dd [] (def x 0))
x ;; => #<Unbound Unbound: #'user/x>
The relevant piece of code can be found here, with the second parameter to lookupVar
triggering the aforementioned interning for non-existing vars here.
The parses then generates an expression that references the previously created var, so the expression logic never leaves the current namespace.
TL;DR: def
is something that the compiler handles in a special kind of way.