On Mon, May 27, 2013 at 5:39 PM, u1204 <d...@axiom-developer.org> wrote:
> The REPL is your best friend. You can "hand execute" small pieces of > code to test your assumptions. > > Common Lisp systems have wonderfully powerful trace functions allowing > arbitrary conditions and actions. > > I haven't seen anything like that in Clojure yet. > What about add-watch? Can be used with any of Clojure's mutable-value containers -- atoms, refs, agents, vars. If one is getting set to an inappropriate value, or you suspect it is, you can attach a watcher to it that will emit a log entry anytime it gets set to a value outside its expected range, including printing a stack trace that should include the spot in the code where this happened. In the case of immutable data or mutable Java objects getting scrozzled, there's always the option of modifying the possible sites of the trouble to log buggy behavior. For instance, if a LinkedBlockingQueue is getting polluted with nils that are making the consumer blow up, adding before (.offer lbq x) something like (if (nil? x) (throw (NullPointerException.))) will move the blowup closer to the actual site of the error and give you an informative stack trace. You might even leave that one in in production, if the thing should (or *will*) die anyway if a nil gets in there, so your user base's bug reports will already have a useful stack trace instead of a useless one. Bad function arguments? Add a :pre clause to blow up immediately with a useful stack trace, if one otherwise doesn't show up or shows up far from the error. Bad values getting into immutable data? Add a (print ...) wherever it's built up using assoc or conj or what-have-you. The only times I've resorted to a debugger myself have been with buggy C code that trashed the stack or heap or jumped off into the middle of nowhere and the resulting stack trace, if existent, didn't point to the true location of the error, or give any useful hints as to where that was, and when diagnosing and fixing deadlocks in Java code. Java dispensed with C's ability to trash the system badly enough to not have a meaningful stack trace (even if it's far from the real error, a Java stack trace is pointing to something *relevant*, like a null where one shouldn't be that you can find all the mutators of; with C in real mode it was frighteningly easy to get no stack trace at all, just a hang, kernel panic, or BSOD, and even in protected mode your bug could systematically destroy all of the data you could use to diagnose it and *then* crash the process) and Clojure has more or less ended the deadlock menace (where being able to see which threads hold what monitors and are waiting for what other monitors was the key debugger killer-feature that stack traces and logging weren't so helpful with) and anything that simply hangs inside the JVM can be re-tried in the context of (def x (Thread. #(hanging-fn args))), (.start x), wait for it to have stopped working, (.getStackTrace x), and check out the stack trace you get to see where hanging-fn and its callees went off the fairway and into the trees (maybe lower x's priority before (.start x) if it wedges a core and that would otherwise make the REPL unresponsive). -- -- 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.