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.

Reply via email to