clojure-dev

Issues: https://clojure.atlassian.net/browse/CLJ | Guide: https://insideclojure.org/2015/05/01/contributing-clojure/
orestis 2020-07-16T13:47:46.402800Z

$ cat src/myns.clj
(ns myns)

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

orestis 2020-07-16T13:48:08.403100Z

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

orestis 2020-07-16T13:49:42.404600Z

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 .

dpsutton 2020-07-16T13:55:01.404900Z

i'm struggling to see anything surprising about this

dpsutton 2020-07-16T13:58:13.405Z

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

dpsutton 2020-07-16T13:58:34.405300Z

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

dpsutton 2020-07-16T13:58:58.405500Z

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

orestis 2020-07-16T14:04:44.405700Z

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

dpsutton 2020-07-16T14:06:47.405900Z

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

bronsa 2020-07-16T14:09:28.406300Z

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

bronsa 2020-07-16T14:09:53.406900Z

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

bronsa 2020-07-16T14:10:51.407500Z

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

orestis 2020-07-16T14:17:41.407600Z

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

seancorfield 2020-07-16T16:02:48.408900Z

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.