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.

Reply via email to