$ cat src/myns.clj
(ns myns)
(defn who-are-you []
(println (ns-name *ns*)))
$ clj
Clojure 1.10.1
user=> (require 'myns)
nil
user=> (myns/who-are-you)
user
nil
I found this very surprising, that *ns*
is not bound in a require call. I discovered this when using *ns*
inside tests to setup various test databases, and all my databases where set to user
.
i'm struggling to see anything surprising about this
cat: src/my: No such file or directory
/t/stuff ❯❯❯ cat src/myns.clj
(ns myns)
(println (ns-name *ns*))
(defn foo []
(println (ns-name *ns*))
(println (namespace ::x)))
t/stuff ❯❯❯ clj
Clojure 1.10.1
user=> (require 'myns)
myns
nil
user=> (myns/foo)
user
myns
nil
user=> ^D
its dynamic. its set at load time but you aren't binding it. it seems like you just want (namespace ::x)
though
Ah, nice trick with (namespace ::x) — it’s within a macro which works at the REPL (because probably CIDER binds *ns*
for me?)
if the macro does it at compile time it should be the captured value you want. if it emits code to do it at run time it should be the same issue. I bet if you remove CIDER it still works
if you want to capture the current value of *ns*
use a let over lambda
(let [*ns* *ns*]
(defn foo [] (println (ns-name *ns*))))
*ns*
is bound in the require call, but the binding is unwound after require returns
I think I will write a blog post to explore this, thanks for the help.
What I do if I want the current namespace name is this:
(def ^:private my-ns *ns*)
Then it is bound to the current ns when the compiler runs and my-ns
ends up with this namespace's name in it.