Thanks Steve! It's clear to me now that I neither understand Clojure's compilation model, nor its special forms. I also see that I probably don't want def to respect dynamic scope, but instead would want a compile-time (non top-level) version of in-ns (or an explanation about why that's a bad idea).
On Friday, May 30, 2014 7:35:53 AM UTC-7, squeegee wrote: > > > On May 30, 2014, at 12:57 AM, ian.tegebo <ian.t...@gmail.com <javascript:>> > 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.