I went to write a context macro so that I could define functions in another 
namespace.  After the obligatory googling, I found "with-ns":

http://richhickey.github.io/clojure-contrib/with-ns-api.html

Clicking through to look at the source, I was surprised to see that "eval" 
was being wrapped around each form in the body of "binding".  I thought, 
"surely forms within the body of a binding expression are evaluated in a 
context of the bindings?!":

user> (ns blah)
nil
blah> (in-ns 'user)
#<Namespace user>
user> (binding [*ns* (the-ns 'blah)] *ns*)
#<Namespace blah>

Okay, no surprise there.  Yet, to my surprise:

user> (binding [*ns* (the-ns 'blah)] (defn foo []))
#'user/foo
user> (binding [*ns* (the-ns 'blah)] (eval '(defn foo [])))
#'blah/foo

The extra eval is necessary after all.  But wait, what does the one without 
eval expand into?

user> (clojure.walk/macroexpand-all '(binding [*ns* (the-ns 'blah)] (defn 
foo [])))
(let*
 []
 (clojure.core/push-thread-bindings
  (clojure.core/hash-map #'*ns* (the-ns 'blah)))
 (try
  (def foo (fn* ([])))
  (finally (clojure.core/pop-thread-bindings))))

Huh.  Alright, let's remind ourselves of what "def" means:

user> (doc def)
-------------------------
def
  (def symbol doc-string? init?)
Special Form
  Creates and interns a global var with the name
  of symbol *in the current namespace (*ns*) *or locates such a var if
  it already exists.  If init is supplied, it is evaluated, and the
  root binding of the var is set to the resulting value.  If init is
  not supplied, the root binding of the var is unaffected.

  Please see http://clojure.org/special_forms#def

Now my confusion: isn't binding *ns* exactly how one sets the "current 
namespace"?  It seems like "def" is not behaving as advertised.  I looked 
briefly at jvm.clojure.lang.Compiler.DefExpr, but I wasn't able to figure 
out why the symbol and namespace resolution going on in that class didn't 
consult thread-bindings (by design?).

Assuming this isn't a bug, what's the rationale for the current behavior?

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to