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




On 13 November 2013 18:52, Mars0i <marsh...@logical.net> wrote:

> Sorry to keep replying to my own posts with corrections: Rereading
> previous posts, I think I understand now that Colin's comments about
> retaining locals were intended to be relevant only to possible future
> facilities (which would go beyond my current knowledge).  But I'm still
> curious about where the -Dblahblah goes, etc.  Thanks.
>
>
> On Tuesday, November 12, 2013 11:15:11 PM UTC-6, Mars0i wrote:
>
>> Colin (or anyone), for a Clojure newbie, could you spell out what you're
>> saying about *compiler-options* and -Dblahblah a little bit further?  I
>> think you're saying that if *compiler-options* is set to
>> :disable-locals-clearing , then values of local variables are available,
>> somehow.  Can I see them from the lein REPL, somehow?  If not, what do I
>> get from :disable-locals-clearing ?
>>
>> It also sounds as if the only way to set *compiler-options* to
>> :disable-locals-clearing is to use 
>> -Dclojure.compile.disable-locals-clearing=true
>> .  Where would I put that in a Leiningen project file?  After :jvm-opts or
>> :javac-options?  Somewhere else?  (I experimented with both, and with
>> trying to set *command-options* in various ways, but I'm not what effect I
>> should see.)
>>
>> Thanks-
>> Marshall
>>
>> (Also, another big +1 for Lee's original comments, and thanks for all of
>> the debugger suggestions from others.  Locals are especially important when
>> there's no state.  I just recently started rewriting a Common Lisp
>> application.  The code had gotten too convoluted; parts of it are very old,
>> with many layers of accretions.  I've been doing the rewrite in Clojure as
>> my first Clojure project.  I'm seriously wondering at this moment, though,
>> whether I should stop and do the rewrite in CL instead, despite several
>> advantages of Clojure for me.  Being able to easily look at any data
>> structure at any time in the CL version of this application has been
>> absolutely crucial in the past.)
>>
>> On Friday, November 8, 2013 11:13:01 PM UTC-6, Colin Fleming wrote:
>>>
>>> One quick clarification about -Dclojure.compile.disable-locals-clearing=true
>>> which bit me - this is actually read in clojure.main, which uses it to
>>> initialise the *compiler-options* var. This means that if you start your
>>> app in any other way (I'm not sure if lein duplicates the clojure.main
>>> functionality) setting this system property doesn't do anything.
>>>
>>>
>>> On 8 November 2013 10:22, Alex Miller <al...@puredanger.com> wrote:
>>>
>>>> I believe the locals are actually *not* available because they are
>>>> proactively cleared to help GC.
>>>>
>>>> Setting the *compiler-options* var with :disable-locals-clearing can
>>>> turn that off. Which is probably what you often want in dev, but is not the
>>>> default.  You can also set this via command line with
>>>> -Dclojure.compile.disable-locals-clearing=true
>>>>
>>>>
>>>> On Thursday, November 7, 2013 11:32:29 AM UTC-6, Lee wrote:
>>>>
>>>>>
>>>>> I'd like to chime in here from a background that involved a lot of
>>>>> Common Lisping back in the day.
>>>>>
>>>>> I have been continually dismayed, as I've moved further from Common
>>>>> Lisp, that debugging facilities that are so basic and ubiquitous and
>>>>> helpful in that world are considered exotic or specialized or necessarily
>>>>> tied to particular IDEs or tool chains in other language ecosystems.
>>>>>
>>>>> Even more basic (and useful, in my experience) than things like
>>>>> steppers or the ability to set break points is the ability just to see the
>>>>> values of locals when an error occurs. This is so obviously useful, and so
>>>>> obviously doable (for decades), that I'm really quite stunned that it's so
>>>>> complicated to do in Clojure and tied to a particular toolset if you can 
>>>>> do
>>>>> it at all.
>>>>>
>>>>> In Common Lisp when you hit an error you're thrown into a break loop
>>>>> REPL in which you can view locals, move up and down the stack, and do lots
>>>>> of other fancier things (re-binding things, restarting...) that are
>>>>> probably useful in some situations, but just being able to see the locals
>>>>> is, in my experience, the really huge win. It doesn't matter what IDE
>>>>> you're using or if you're running it from a command line or whatever --
>>>>> it's part of the language and easy to access no matter how you write and
>>>>> run your code. And my guess is that every Common Lisper takes advantage of
>>>>> this frequently. Different implementations/environments provide different
>>>>> modes of access to this information (e.g. some are GUI-based, and in emacs
>>>>> you can have interactive access to it using interaction conventions that
>>>>> seemed like a good idea in the 1970s :-), but there's always some way to
>>>>> get the information.
>>>>>
>>>>> By contrast in Clojure this information seems really hard to come by.
>>>>> I saw and was excited by a Ritz video -- and I note the enthusiastic
>>>>> applause from the crowd when it was shown that you could see locals 
>>>>> (gasp!)
>>>>> -- but my understanding is that this functionality requires commitment to
>>>>> an Emacs-based tool set with all that that implies (which is a lot, IMHO).
>>>>>
>>>>> When I hit an error running my code from "lein run" or from Clooj or
>>>>> from Eclipse/CCW (or I think from any other way that I might run it) I get
>>>>> (or can easily get) a backtrace that shows the function call stack at the
>>>>> time of the error... which is good, but surely (?) the locals are also
>>>>> available when the backtrace is produced and I really also want to see
>>>>> those. The ability to browse and navigate this information dynamically, as
>>>>> in a Common Lisp break loop, is cool but I can understand that something
>>>>> about the Clojure/JVM execution architecture might make that difficult --
>>>>> maybe that really would have to be tied to a particular IDE? However, if 
>>>>> it
>>>>> would just dump all of the values of the locals to standard output, just
>>>>> like it does already with the trace, then I'd be plenty happy since I 
>>>>> could
>>>>> dig through that output to find what I need but can't currently get. (Yes,
>>>>> dumping the values of all of the locals might produce a lot of output and
>>>>> yes, one might want to make this an option that could be turned off or on,
>>>>> maybe including options re: limits on how much of sequences to print, 
>>>>> etc.)
>>>>>
>>>>> I guess the bottom line of this long message (sorry) is that I hope
>>>>> that some of the great tool developers in this community will continue to
>>>>> consider providing things like debugging tools that are as untethered as
>>>>> possible from particular IDEs. My impression is that nrepl (and maybe 
>>>>> other
>>>>> projects) are intended to help "untether" things in this way, but it still
>>>>> seems like a lot of people assume that something like access to locals
>>>>> should naturally be tied to a specific IDE. From my perspective that seems
>>>>> like a really unfortunate assumption. I realize that debugging tools are
>>>>> unlikely to become "part of the language" in Clojure as they are in Common
>>>>> Lisp, but I think there's an important middle ground between that and 
>>>>> being
>>>>> available only within some specific IDE.
>>>>>
>>>>> Thanks,
>>>>>
>>>>>  -Lee
>>>>>
>>>>>
>>>>> > philli...@newcastle.ac.uk (Phillip Lord) writes:
>>>>> >
>>>>> >> Ritz does some things, but it doesn't do step through like edebug.
>>>>> >>
>>>>> >> I've never found anything as nice as edebug in any language; I
>>>>> guess,
>>>>> >> it's the big advantage of running your editor and whatever you are
>>>>> >> debugging in the environment.
>>>>>
>>>>>  --
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Clojure" group.
>>>> To post to this group, send email to clo...@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+u...@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+u...@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.
>

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