Search code examples
clojurenamespacesfunctiondefn

What namespaces Clojure uses for def-ing


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.
  • I know that using def inside function is probably not very idiomatic. However, this is just extracted essence of a bigger problem I ran into.

Solution

  • 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.