Search code examples
clojurenamespaces

Why does "use" in Clojure call "in-ns" to return to the original namespace?


In Clojure use loads a lib and in addition refers to the lib's namespace.

load does not change the current namespace.

Then what is the purpose of the in-ns command that is implicitly called when a lib is loaded with use?

user=> (use 'project.core :verbose)
(clojure.core/load "/project/core")
(clojure.core/in-ns 'user)
(clojure.core/refer 'project.core)

In other words, isn't (clojure.core/in-ns 'user) in the previous example unnecessary?


Solution

  • It doesn't actually call in-ns – it only prints this line when "loading verbosely" (that is, if you pass in :verbose as an option to use) so that you know which namespace the referring takes place in. It would also do that if you called require with :as to make clear which namespace the alias would be created in:

    user=> (require '[clojure.set :as set] :verbose)
    (clojure.core/load "/clojure/set")
    (clojure.core/in-ns 'user)
    (clojure.core/alias 'set 'clojure.set)
    

    This is useful when the initial load causes more namespaces to be loaded recursively. For example, here's the output of (require '[clojure.core.rrb-vector :as fv] :verbose) (arguably the refer lines could use the explanatory in-ns line treatment as well):

    (clojure.core/load "/clojure/core/rrb_vector")
    (clojure.core/load "/clojure/core/rrb_vector/protocols")
    (clojure.core/refer 'clojure.core.rrb-vector.protocols :refer '[slicev splicev])
    (clojure.core/load "/clojure/core/rrb_vector/nodes")
    (clojure.core/refer 'clojure.core.rrb-vector.nodes :refer '[ams object-am object-nm primitive-nm empty-pv-node empty-gvec-node])
    (clojure.core/load "/clojure/core/rrb_vector/rrbt")
    (clojure.core/refer 'clojure.core.rrb-vector.protocols :refer '[PSliceableVector slicev PSpliceableVector splicev])
    (clojure.core/refer 'clojure.core.rrb-vector.nodes :refer '[ranges overflow? last-range regular-ranges first-child last-child remove-leftmost-child replace-leftmost-child replace-rightmost-child fold-tail new-path index-of-nil object-am object-nm primitive-nm])
    (clojure.core/load "/clojure/core/rrb_vector/transients")
    (clojure.core/refer 'clojure.core.rrb-vector.nodes :refer '[ranges last-range])
    (clojure.core/refer 'clojure.core.rrb-vector.transients :refer '[transient-helper])
    (clojure.core/load "/clojure/core/rrb_vector/fork_join")
    (clojure.core/load "/clojure/core/reducers")
    (clojure.core/in-ns 'clojure.core.reducers)
    (clojure.core/alias 'walk 'clojure.walk)
    (clojure.core/in-ns 'clojure.core.rrb-vector.fork-join)
    (clojure.core/alias 'r 'clojure.core.reducers)
    (clojure.core/in-ns 'clojure.core.rrb-vector.rrbt)
    (clojure.core/alias 'fj 'clojure.core.rrb-vector.fork-join)
    (clojure.core/refer 'clojure.core.protocols :refer '[IKVReduce])
    (clojure.core/in-ns 'clojure.core.rrb-vector.rrbt)
    (clojure.core/alias 'r 'clojure.core.reducers)
    (clojure.core/refer 'clojure.core.reducers :refer '[CollFold coll-fold])
    (clojure.core/refer 'clojure.core.rrb-vector.rrbt :refer '[as-rrbt])
    (clojure.core/load "/clojure/core/rrb_vector/interop")
    (clojure.core/refer 'clojure.core.rrb-vector.protocols :refer '[PSliceableVector slicev PSpliceableVector splicev])
    (clojure.core/refer 'clojure.core.rrb-vector.rrbt :refer '[as-rrbt])
    (clojure.core/in-ns 'user)
    (clojure.core/alias 'fv 'clojure.core.rrb-vector)
    

    Here's the relevant fragment of the source of clojure.core/load-lib (which is where the printout comes from):

    ;; as of Clojure 1.6.0
    (when (and need-ns *loading-verbosely*)
      (printf "(clojure.core/in-ns '%s)\n" (ns-name *ns*)))
    (when as
      (when *loading-verbosely*
        (printf "(clojure.core/alias '%s '%s)\n" as lib))
      (alias as lib))
    

    need-ns is a local whose value is (or as use) – that is, truthy if an :as alias was specified or the load was caused by a use.

    Say (source clojure.core/load-lib) at the REPL if you'd like to examine the entire function.