On May 30, 2014, at 12:57 AM, ian.tegebo <ian.teg...@gmail.com> wrote:

> I don't see the reason why def should behave as it currently does; it seems 
> like it should lookup the current thread-binding for *ns*, making the second 
> case's use of eval unnecessary.  Since it doesn't, I'd like to know why it 
> couldn't (or shouldn't) do the thing that seems more intuitive.


One reason is performance.

The compile-time resolution of:

  - symbols into fully qualified symbols, and then
  - fully qualified symbols into direct references to the vars they represent

is important in allowing Clojure code to execute as fast as it does. These are 
relatively time consuming operations. Deferring them to execution time would 
make Clojure code execution slower to an unacceptable degree. Instead, they are 
done once when the code is compiled and in the general case executed many times 
without further lookups.

In your particular example, the code is compiled once, executed, and then not 
used again so the performance distinction doesn't matter. However, the repl and 
eval don't get any special treatment from the compiler, so you see the same 
behavior using them as you do when you load a library full of code using 
:require in an ns form.

Another design choice for the Clojure compiler that impacts your example is 
that each top-level form is completely compiled before any part of it is 
executed [1]. There's a nice writeup of another similar implication of that 
here: http://technomancy.us/143 .

The distinction between compile time and execution time for Clojure code is 
something that rarely has an impact on understanding the behavior of the code. 
You've found a case where the distinction does matter. The doc for def talks 
about the "current" namespace without giving a detailed description of what 
instant of time "current" refers to. It turns out to be "current at the time 
the code is compiled", not "current at the time the code is executed".

In the rare case that the binding of *ns* changes between those times, the 
behavior can be confusing. One way to avoid this confusion is to keep all defs 
at the top level and treat *ns* as something that can be set! or manipulated 
with the associated tools like in-ns, but not bound using bind.

--Steve

[1] Except a top-level "do" in Clojure 1.1+ as described in the blog post

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