Search code examples
clojurenamespaces

how symbols in use clause be applied in current namespace


I'm reviewing for core.match test

(ns clojure.core.match.test.regex
  (:use [clojure.core.match :only [match]])
  (:use clojure.core.match.regex)
  (:use clojure.test))

(deftest basic-regex
     (is (= (match ["asdf"]
                   [#"asdf"] 1
                   :else 2)
            1)))

When I ran these code in clojure.1.10, but wondering why how

 (:use clojure.core.match.regex)

works ? I can understand match is being used , If I don't include regex, the behavior will fail of course.

Thanks for your help.


Solution

  • The ns expression at the top of a namespace is a macro that expands to some code that makes sure all the forms in the libraries required get evaluated, and then makes some symbols in the current namespace refer to functions and such from the libraries.

           (macroexpand-1
            `(ns clojure.core.match.test.regex
               (:use [clojure.core.match :only [match]])
               (:use clojure.core.match.regex)
               (:use clojure.test))))
    (do
    
     ;; Create the namespace and then switch the compilers context to it,
     ;; so things defined when evaluating this file will happen to this namespacee
     (clojure.core/in-ns 'clojure.core.match.test.regex)
    
    
     ;; For every namespace required, or referred, evaluate every form in them 
     ;; including any `ns` forms which will in turn do that for other namespaces.
     (clojure.core/with-loading-context
      (clojure.core/refer 'clojure.core)
      (clojure.core/use '[clojure.core.match :only [user/match]])
      (clojure.core/use 'clojure.core.match.regex)
      (clojure.core/use 'clojure.test))
    
     ;; do some additional housekeeping etc.
     (if
      (.equals 'clojure.core.match.test.regex 'clojure.core)
      nil
      (do
       (clojure.core/dosync
        (clojure.core/commute
         @#'clojure.core/*loaded-libs*
         clojure.core/conj
         'clojure.core.match.test.regex))
       nil)))
    nil
    

    The actual work of loading all the forms in the library is done by either use or require.

    clojure.core/use, is generally the older form. It evaluates every expression in the file form top to bottom, and makes the current namespace refer to all the symbols in the other namespace by default unless you tell it otherwise with the :only option.

    and clojure.core/require is the newer form. It also starts off by evaluating all the expressions, in the namespace it's pulling in,from top to bottom, and then it only makes the current namespace refer to the specific symbols you tell it to in the :refer parameter.

    In general new code tends to prefer require over using use.