what is the parameter to ns?
what is the parameter to ns ? the documentation says something, but it's not clear (to me, at least)
my-new-namespace=> (doc ns)
-------------------------
clojure.core/ns
([name docstring? attr-map? references*])
Macro
Sets *ns* to the namespace named by name (unevaluated), creating it
if needed.
...the rest of the documentation was not copied
the confusion comes from all the other functions that play with namespaces:
user=> (find-ns 'my-new-namespace开发者_运维百科)
nil
user=> (remove-ns 'my-new-namespace)
nil
user=> (create-ns 'my-new-namespace)
#<Namespace my-new-namespace>
user=> (ns 'my-new-namespace)
java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol (NO_SOURCE_FILE:26)
user=> (ns my-new-namespace)
nil
my-new-namespace=>
find-ns, create-ns, remove-ns
take my-new-namespace
quoted, while ns
takes my-new-namespace
unquoted
so, what is the deal ? why some get a quoted form and others get and unquoted form of my-new-namespace
?
what is, in each case, my-new-namespace
?
ps: think i figured out the answer to this as i was writing the question here, but it seemed and interesting exercise, so the question still got posted :D
ns is a macro and under the hood if quotes the name to save you the trouble:
user> (macroexpand '(ns foo))
(do (clojure.core/in-ns (quote foo)) (clojure.core/with-loading-context
(clojure.core/refer (quote clojure.core))))
the other functions cant get away with unquoted arguments because they are functions, and functions have there arguments evaluated first.
the ns macro, as a macro, gets to look at and twiddle its arguments before they are evaluated so it can get at the my-new-namespace before the reader attempts to look it up as a variable name.
in short this saves wear and tare on your keyboard and wrists ;) Just kidding, the in both cases what the function receives is a symbol they just differ in what you have to do to pass them that symbol.
for comparason; if you where to go ahead and pass (ns 'my-new-namespace)
it would get the symbol 'my-new-namespace
quote and all! you likely don't want the quote to be part of the name space.
if you want to make it consistent you could write wrapper macros that take unquoted symbols for the rest of the namespace functions that simply quote the first argument and return a call to the real function (remember that macros return the code to be called)
(defmacro my-find-ns [name]
`(find-ns (quote ~name)))
though this would break "the first rule of macro club"
the error about the argument being a list is caused by it attempting to use (quote my-new-namespace)
as a name
user> (macroexpand '(ns 'foo))
(do (clojure.core/in-ns (quote (quote foo))) (clojure.core/with-loading-context
(clojure.core/refer (quote clojure.core))))
精彩评论