Hi Marshall,

You'll only see a difference due to locals clearing if you're stepping with
a debugger and looking at locals in your local stack frame or in the frames
above it. In your example, the ability to pause when an exception is thrown
is a capability your debugger provides. Cursive does provide this (although
I need to test it thoroughly, most of the functionality is provided by
IntelliJ and I haven't tested it all with Clojure yet), I'm not sure about
other debuggers. So if your debugger provides that capability, when you
pause on the thrown exception, if you didn't have locals clearing disabled
when that code was compiled you'll see the value of n as null since the
compiler has inferred that the value is never used in the branch you took
(the branch throwing the exception) and has nulled it out. If you had
locals clearing disabled when that code was compiled, then you will
correctly see the value of n as 15, yes.

Cheers,
Colin


On 14 November 2013 08:53, Mars0i <marsh...@logical.net> wrote:

> Thanks Colin!  Wow--that's extremely helpful.  The concepts are very clear
> now, and I now understand that it's a map *compiler-options* is supposed to
> be set to.  What I was trying before wasn't right.
>
> No matter what I do, I am not seeing an effect on the value of
> *compiler-options* from the command line option.  Tried
>    :jvm-opts ["-Dclojure.compiler.disable-locals-clearing=true"]
> in a Leiningen project.clj, both with and without compiling to class files
> ahead of time.  Tried it starting Clojure with a java command line from the
> prompt.
>
> I can't set the value of *compiler-options* with set!, but I'm able to set
> *compiler-options* with binding, and see that it's bound to
> {:disable-locals-clearing true} inside the binding form (of course).
>
> I'm still not clear on what effect this should have.  I can refer to a
> local variable inside its scope, but that's nothing special.  Is
> :disable-locals-clearing = true supposed to allow me to be able to
> reference a local outside of its scope?  (A bad thing in general, but good,
> sometimes, for debugging?)  For example, if I compile this:
>
> (defn yo [n]
>   (if (= n 15)
>     (throw (Exception. (format "Yow!")))
>     (if (<= n 0)
>       "Done!"
>       (yo (dec n)))))
>
> with *compiler-options* set to {:disable-locals-clearing true}, is there a
> way to see, after the exception is thrown, that n had the value 15?
>
> Thanks-
>
> Marshall
>
>
> On Wednesday, November 13, 2013 3:45:27 AM UTC-6, Colin Fleming wrote:
>>
>> Hi Marshall,
>>
>> Sure. Clojure implements locals clearing, which means that the compiler
>> will set local variables to null when it knows that the value of those
>> variables won't be used any more. This allows the garbage collector to
>> reclaim any values that those variables were pointing to, which is
>> particularly important in the case of large lazy sequences, which cache the
>> values they return to ensure that the same sequence always returns the same
>> values.
>>
>> What you'll see if this option is not set is that the majority of local
>> variables (and of course, always the one you actually want to look at),
>> especially further up the stack frames, will be set to null even if your
>> code doesn't do so. This can be very confusing and/or frustrating when
>> debugging.
>>
>> *compiler-options* is a dynamic var that controls various compiler
>> options, although I believe disabling locals clearing is the only one at
>> present. You control locals clearing by setting the value of
>> :disable-locals-clearing in this map to true. There are various ways to do
>> this - you could set it explicitly in the REPL, or you can set the system
>> property "clojure.compiler.disable-locals-clearing" to the value you
>> would like it to be set to. You can see the code that does this 
>> here<https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compile.java#L58>,
>> and if you're really interested the whole change is 
>> here<https://github.com/clojure/clojure/commit/4036c7720949cb21ccf53c5c7c54ed1daaff2fda>.
>> You would set this system property in your JVM args, so if you're running
>> an app from the command line using "java ..." then just add
>> -Dclojure.compiler.disable-locals-clearing=true to your command line, or
>> you can add it to your jvm-opts in leiningen as shown elsewhere in this
>> thread.
>>
>> However note that the code I linked to above is actually in the main
>> function of the compiler (I was wrong in my previous message, it's not
>> clojure.main) so this system property will only apply when AOTing your
>> code, not running it normally. In that case you'll have to do something
>> like:
>>
>> (set! *compiler-options* {:disable-locals-clearing true})
>>
>> or
>>
>> (binding [*compiler-options* (assoc *compiler-options*
>> :disable-locals-clearing true)]
>>   ... your code here ...)
>>
>> somewhere right near the start of your code (I'm not on a dev machine so
>> I haven't tested those, but that's the idea). The problem here is that
>> you'll have to ensure that this variable is set before the code you're
>> interested in is compiled! i.e. before its namespace is require'd, in the
>> majority of cases. This is not too much of a problem in the REPL when you
>> can always re-evaluate a namespace to recompile it, but it's a PITA in an
>> application. In Cursive I actually do it in Java before I bootstrap Clojure.
>>
>> IMO this whole process is a fairly confusing which is unfortunate - I
>> think a few changes would have made it much easier to work with, but that's
>> how it currently works. Let me know if you have any more questions!
>>
>> Cheers,
>> Colin
>>
>  --
> --
> 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/groups/opt_out.
>

-- 
-- 
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/groups/opt_out.

Reply via email to