Fork me on GitHub
#clojure-dev
<
2020-07-16
>
orestis13:07:46

$ cat src/myns.clj
(ns myns)

(defn who-are-you []
  (println (ns-name *ns*)))

orestis13:07:08

$ clj
Clojure 1.10.1
user=> (require 'myns)
nil
user=> (myns/who-are-you)
user
nil

orestis13:07:42

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 .

dpsutton13:07:13

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)))

dpsutton13:07:34

t/stuff ❯❯❯ clj
Clojure 1.10.1
user=> (require 'myns)
myns
nil
user=> (myns/foo)
user
myns
nil
user=> ^D

dpsutton13:07:58

its dynamic. its set at load time but you aren't binding it. it seems like you just want (namespace ::x) though

orestis14:07:44

Ah, nice trick with (namespace ::x) — it’s within a macro which works at the REPL (because probably CIDER binds *ns* for me?)

dpsutton14:07:47

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

orestis14:07:41

I think I will write a blog post to explore this, thanks for the help.

dpsutton13:07:01

i'm struggling to see anything surprising about this

bronsa14:07:28

if you want to capture the current value of *ns* use a let over lambda

bronsa14:07:53

(let [*ns* *ns*] 
  (defn foo [] (println (ns-name *ns*))))

bronsa14:07:51

*ns* is bound in the require call, but the binding is unwound after require returns

seancorfield16:07:48

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.