special formsince v0.0-927 clojure.core/nsEdit
(ns name docstring? attr-map? references*)


Sets the namespace of the file.

ns must be the first form in a .cljs file and there can only be one ns declaration per file. Namespaces must match the file name of their respective .cljs files, with the exception that dashes in namespaces become underscores in filenames. Thus, (ns foo.bar-biz.baz) should be the first form in file foo/bar_biz/baz.cljs.

references can be zero or more forms used to import other namespaces, symbols, and libraries into the current namespace.

(ns example.core

  ;; for excluding or renaming clojure symbols
    :exclude []
    :rename {})

  ;; for importing goog classes and enums
    (lib.ns Ctor*))

    [lib.ns :refer []
            :refer-macros []
            :rename {}
            :include-macros true|false
            :as alias]

    [lib.ns :only []
            :rename {}]

    [lib.ns :refer []
            :rename {}
            :as alias]

    [lib.ns :only []
            :rename {}]

See Also:

Source docstring:
You must currently use the ns form only with the following caveats

  * You must use the :only form of :use
  * :require supports :as, :refer, and :rename
    - all options can be skipped
    - in this case a symbol can be used as a libspec directly
      - that is, (:require lib.foo) and (:require [lib.foo]) are both
        supported and mean the same thing
    - :rename specifies a map from referred var names to different
      symbols (and can be used to prevent clashes)
    - prefix lists are not supported
  * The only options for :refer-clojure are :exclude and :rename
  * :import is available for importing Google Closure classes
    - ClojureScript types and records should be brought in with :use
      or :require :refer, not :import ed
  * Macros must be defined in a different compilation stage than the one
    from where they are consumed. One way to achieve this is to define
    them in one namespace and use them from another. They are referenced
    via the :require-macros / :use-macros options to ns
    - :require-macros and :use-macros support the same forms that
      :require and :use do

Implicit macro loading: If a namespace is required or used, and that
namespace itself requires or uses macros from its own namespace, then
the macros will be implicitly required or used using the same
specifications. Furthermore, in this case, macro vars may be included
in a :refer or :only spec. This oftentimes leads to simplified library
usage, such that the consuming namespace need not be concerned about
explicitly distinguishing between whether certain vars are functions
or macros. For example:

(ns testme.core (:require [cljs.test :as test :refer [test-var deftest]]))

will result in test/is resolving properly, along with the test-var
function and the deftest macro being available unqualified.

Inline macro specification: As a convenience, :require can be given
either :include-macros true or :refer-macros [syms...]. Both desugar
into forms which explicitly load the matching Clojure file containing
macros. (This works independently of whether the namespace being
required internally requires or uses its own macros.) For example:

(ns testme.core
(:require [foo.core :as foo :refer [foo-fn] :include-macros true]
          [woz.core :as woz :refer [woz-fn] :refer-macros [app jx]]))

is sugar for

(ns testme.core
(:require [foo.core :as foo :refer [foo-fn]]
          [woz.core :as woz :refer [woz-fn]])
(:require-macros [foo.core :as foo]
                 [woz.core :as woz :refer [app jx]]))

Auto-aliasing clojure namespaces: If a non-existing clojure.* namespace
is required or used and a matching cljs.* namespace exists, the cljs.*
namespace will be loaded and an alias will be automatically established
from the clojure.* namespace to the cljs.* namespace. For example:

(ns testme.core (:require [clojure.test]))

will be automatically converted to

(ns testme.core (:require [cljs.test :as clojure.test]))
Parser code @ clojurescript:src/main/clojure/cljs/analyzer.cljc
(defmethod parse 'ns
  [_ env [_ name & args :as form] _ opts]
  (when-not *allow-ns*
    (throw (error env "Namespace declarations must appear at the top-level.")))
  (when-not (symbol? name)
    (throw (error env "Namespaces must be named by a symbol.")))
  (let [name (cond-> name (:macros-ns opts) macro-ns-name)]
    (let [segments (string/split (clojure.core/name name) #"\.")]
      (when (= 1 (count segments))
        (warning :single-segment-namespace env {:name name}))
      (let [segment (some js-reserved segments)]
        (when (some? segment)
          (warning :munged-namespace env {:name name})))
      (find-def-clash env name segments)
         (when (some (complement util/valid-js-id-start?) segments)
               (str "Namespace " name " has a segment starting with an invaild "
                    "JavaScript identifier"))))))
    (let [docstring    (when (string? (first args)) (first args))
          mdocstr      (-> name meta :doc)
          args         (if (some? docstring) (next args) args)
          metadata     (when (map? (first args)) (first args))
          args         (desugar-ns-specs
                         #?(:clj  (rewrite-cljs-aliases
                                    (if metadata (next args) args))
                            :cljs (if (some? metadata) (next args) args)))
          {:keys [as-aliases] args :libspecs} (nses/elide-aliases-from-ns-specs args)
          name         (vary-meta name merge metadata)
          {excludes :excludes core-renames :renames} (parse-ns-excludes env args)
          core-renames (reduce (fn [m [original renamed]]
                                 (assoc m renamed (symbol "cljs.core" (str original))))
                         {} core-renames)
          deps         (atom [])
          ;; as-aliases can only be used *once* because they are about the reader
          aliases      (atom {:fns as-aliases :macros as-aliases})
          spec-parsers {:require        (partial parse-require-spec env false deps aliases)
                        :require-macros (partial parse-require-spec env true deps aliases)
                        :use            (comp (partial parse-require-spec env false deps aliases)
                                          (partial use->require env))
                        :use-macros     (comp (partial parse-require-spec env true deps aliases)
                                          (partial use->require env))
                        :import         (partial parse-import-spec env deps)}
          valid-forms  (atom #{:use :use-macros :require :require-macros :import})
          reload       (atom {:use nil :require nil :use-macros nil :require-macros nil})
          reloads      (atom {})
          {uses :use requires :require renames :rename
           use-macros :use-macros require-macros :require-macros
           rename-macros :rename-macros imports :import :as params}
            (fn [m [k & libs :as libspec]]
              (when-not (#{:use :use-macros :require :require-macros :import} k)
                (throw (error env (str "Only :refer-clojure, :require, :require-macros, :use, :use-macros, and :import libspecs supported. Got " libspec " instead."))))
              (when-not (@valid-forms k)
                (throw (error env (str "Only one " k " form is allowed per namespace definition"))))
              (swap! valid-forms disj k)
              ;; check for spec type reloads
              (when-not (= :import k)
                (when (some? (some #{:reload} libs))
                  (swap! reload assoc k :reload))
                (when (some? (some #{:reload-all} libs))
                  (swap! reload assoc k :reload-all)))
              ;; check for individual ns reloads from REPL interactions
              (when-let [xs (seq (filter #(-> % meta :reload) libs))]
                (swap! reloads assoc k
                  (zipmap (map first xs) (map #(-> % meta :reload) xs))))
              (apply merge-with merge m
                (map (spec-parsers k)
                  (remove #{:reload :reload-all} libs))))
            {} (remove (fn [[r]] (= r :refer-clojure)) args))
          ;; patch `require-macros` and `use-macros` in Bootstrap for namespaces
          ;; that require their own macros
          #?@(:cljs [[require-macros use-macros]
                     (map (fn [spec-map]
                            (if (:macros-ns opts)
                              (let [ns (symbol (subs (str name) 0 (- (count (str name)) 7)))]
                                (reduce (fn [m [k v]]
                                          (cond-> m
                                            (not (symbol-identical? v ns))
                                            (assoc k v)))
                                  {} spec-map))
                              spec-map)) [require-macros use-macros])])]
      (set! *cljs-ns* name)
      (let [ns-info
            {:as-aliases     as-aliases
             :name           name
             :doc            (or docstring mdocstr)
             :excludes       excludes
             :use-macros     use-macros
             :require-macros require-macros
             :rename-macros  rename-macros
             :uses           uses
             :requires       requires
             :renames        (merge renames core-renames)
             :imports        imports}]
        (swap! env/*compiler* update-in [::namespaces name] merge ns-info)
        (merge {:op      :ns
                :env     env
                :form    form
                :deps    (into [] (distinct @deps))
                :reload  @reload
                :reloads @reloads}
          (cond-> ns-info
            (@reload :use)
            (update-in [:uses]
              (fn [m] (with-meta m {(@reload :use) true})))
            (@reload :require)
            (update-in [:requires]
              (fn [m] (with-meta m {(@reload :require) true})))))))))

Emitting code @ clojurescript:src/main/clojure/cljs/compiler.cljc
(defmethod emit* :ns
  [{:keys [name requires uses require-macros reloads env deps]}]
  (emitln "goog.provide('" (munge name) "');")
  (when-not (= name 'cljs.core)
    (emitln "goog.require('cljs.core');")
    (when (-> @env/*compiler* :options :emit-constants)
      (emitln "goog.require('" (munge ana/constants-ns-sym) "');")))
  (load-libs requires nil (:require reloads) deps name)
  (load-libs uses requires (:use reloads) deps name))