I look at the implementation of the old c-ns tab macro:
(defmacro with-ns "Evaluates body in another namespace. ns is either a namespace object or a symbol. This makes it possible to define functions in namespaces other than the current one." [ns & body] `(binding [*ns* (the-ns ~ns)] ~@ (map (fn [form] `(eval '~form)) body)))
What I do not understand is the need for an examination of the body. In other words, why this does not work when I want to access elements in the target namespace inside the body without eval (example below).
user=> (defmacro wns [ns & body] `(binding [*ns* (the-ns ~ns)] ~@body )) #'user/wns user=> (create-ns 'boofar) #<Namespace boofar> user=> (in-ns 'boofar) #<Namespace boofar> boofar=> (clojure.core/refer-clojure) nil boofar=> (defn xx [ab] (str ab)) #'boofar/xx boofar=> (xx 5 6) "56" boofar=> (in-ns 'user) #<Namespace user> user=> (with-ns 'boofar (println *ns*) (xx 5 6)) #<Namespace boofar> "56" user=> (wns 'boofar (println *ns*) (xx 5 6)) CompilerException java.lang.RuntimeException: Unable to resolve symbol: xx in this context, compiling:(blardy/blardy/form-init3758076021118964250.clj:1:29) user=> (wns 'boofar (println *ns*)) #<Namespace boofar> nil
I'm fine with that. I really do not mind, but I would like to understand what is happening here. xx clearly exists in the boofar namespace, and clicking on ns binding should put me there, but I cannot name it directly, however I can name something in clojure.core that was passed. In case you are interested, I tried rewriting the macro to use in-ns with the appropriate try / finally, and the result will be the same.
Thanks!
change
Added macro example using in-ns . The results are the same as without.
user=> (defmacro wins [ns & body] `(let [orig-ns# (ns-name *ns*)] (try (in-ns ~ns) ~@body (finally (in-ns orig-ns#)))))
Advanced Macro ...
user=> (pprint (macroexpand-all '(wins 'boofar2 (xx 7 8)))) (let* [orig-ns__4137__auto__ (clojure.core/ns-name clojure.core/*ns*)] (try (clojure.core/in-ns 'boofar2) (xx 7 8) (finally (clojure.core/in-ns orig-ns__4137__auto__))))
Using it ...
user=> (defn xx [ab] (str "user/xx [" a " " b "]")) user=> (in-ns 'boofar2) boofar2=> (defn xx [ab] (str "boofar2/xx [" a " " b "]")) boofar2=> (in-ns 'user) user=> (wins 'boofar2 (xx 7 8)) "user/xx [7 8]"
source share