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.