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.