I just discovered that the following doesnt work.
(ns some-ns
(:require [clojure.spec.alpha :as s]))
(defn foo []
(= (resolve 's/*) (resolve 'clojure.spec.alpha/*)))
because when foo
gets called by the application, the name space might not have required [clojure.spec.alpha :as s]
Instead, I did the following and it seems to work.
(ns some-ns
(:require [clojure.spec.alpha :as s]))
(defn foo []
(binding [*ns* (find-ns 'some-ns)]
(= (resolve 's/*) (resolve 'clojure.spec.alpha/*))))
You get different results than this in a REPL?
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (resolve 's/*)
#'clojure.spec.alpha/*
user=> (resolve 'clojure.spec.alpha/*)
#'clojure.spec.alpha/*
user=> (= (resolve 's/*) (resolve 'clojure.spec.alpha/*))
true
Note that you have no *
after clojure.spec.alpha/
I do not know if that is a typo in chat, or reflects your actual code.
yes a copy/paste error. corrected, should be /* everywhere
Now I see clojure.spec.alpha
. Did you intend to use clojure.spec.alpha/*
instead?
defn foo
is in the namespace some-ns
? If so, how does some part of your code call foo
without first require'ing some-ns
?
important observation is that the behavior of resolve
depends on the value of *ns*
when foo
is called, not when foo
is defined.
the caller of foo has required some-ns, but he might not have aliased closure.spec.alpha to s
Got it. Yes, that is true, and resolution of aliases like s
definitely depends upon the namespace in which they are resolved.
i found out because I ran my tests from the repl where I had required spec and aliased to s. But when I tested from lien test
at the comand line, it ran the tests with the user
namespace, which I never tested in.
Alias s
could be not an alias in some namespace, be used for clojure.spec.alpha
in another namespace, and be used for clojure.set
in yet another namespace. Not recommended for developer sanity to use the same alias for different namespaces, but Clojure allows it.
besides, when I develop the code, I use some convention. But I don't impose that convention on my customers who might have very different programming styles. or they theoretically might even be calling my code from java or some such
The doc string for resolve
gives a pretty strong hint about this dependence upon the current value of *ns*
I think all calls to resolve or suspect within code.. I'm thinking of refactoring every call in my program and replacing with ns-resolve so I'll have to think about which ns to use. Then test from repl and also from lein command line as a general pratice
it's on my to-do list.
Using ns-resolve
instead of resolve
sounds like a good idea, if you want to force yourself to be explicit about in which namespace the resolving is performed.
of course nothing prohibits me from using (ns-resolve *ns* foo)
if that's the appropriate one to use.