Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
That looks really very nice. The reader macros are particularly nice because it saves messing around with the structure of your code. Phil dgrnbrg dsg123456...@gmail.com writes: I'd like to point out a similar library I wrote for Clojure called spyscope: https://github.com/dgrnbrg/spyscope With spyscope, you can write a handful of characters and get the stack frame, form, and its value pretty-printed and logged to a queue for future querying. On Thursday, May 30, 2013 8:28:19 PM UTC-4, David Jacobs wrote: That's true -- that's why I wrote up the Letters debugging mini-library for Ruby (lettersrb.com). However, there's friction there, too, and a surprising number of people don't think to do this. On Thursday, May 30, 2013 at 5:25 PM, Timothy Baldridge wrote: Not really true, most of my programs contain this function: (defn debug [x] (pprint x) x) Now I can do this: (comp foo debug bar) Also, with some reader literal magic, I could write something to let me do this: (myfunc foo #dbg bar) On Thu, May 30, 2013 at 6:12 PM, David Jacobs da...@wit.iojavascript:(mailto: da...@wit.io javascript:) wrote: Two more things: 1) printing is often not a viable option for lazily eval-ed sequences or async processes -- the output gets jumbled! And believe me, when a new Clojure dev sees that for the first time, he/she wants to quit. 2) printing is terrible for elegant clojure code -- thing (comp f g h (partial map z)) -- in order to figure out anything about dynamic data flowing through, you have to break apart that composition or add a let binding in one of those functions before returning a value. Both of those involve a lot of friction. On Thursday, May 30, 2013 5:00:13 PM UTC-7, raould wrote: for a long time haskell did not have a debugger. that sucked, imho. -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript:(mailto: clo...@googlegroups.com javascript:) 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 javascript: (mailto: clojure%2b...@googlegroups.com javascript:) 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 javascript: (mailto: clojure%2b...@googlegroups.com javascript:). For more options, visit https://groups.google.com/groups/opt_out. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript:(mailto: clo...@googlegroups.com javascript:) 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 javascript: (mailto: clojure+u...@googlegroups.com javascript:) 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 javascript: (mailto: clojure+u...@googlegroups.com javascript:). For more options, visit https://groups.google.com/groups/opt_out. -- -- Phillip Lord, Phone: +44 (0) 191 222 7827 Lecturer in Bioinformatics, Email: phillip.l...@newcastle.ac.uk School of Computing Science, http://homepages.cs.ncl.ac.uk/phillip.lord Room 914 Claremont Tower, skype: russet_apples Newcastle University, twitter: phillord NE1 7RU -- -- 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
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
I'd like to point out a similar library I wrote for Clojure called spyscope: https://github.com/dgrnbrg/spyscope With spyscope, you can write a handful of characters and get the stack frame, form, and its value pretty-printed and logged to a queue for future querying. On Thursday, May 30, 2013 8:28:19 PM UTC-4, David Jacobs wrote: That's true -- that's why I wrote up the Letters debugging mini-library for Ruby (lettersrb.com). However, there's friction there, too, and a surprising number of people don't think to do this. On Thursday, May 30, 2013 at 5:25 PM, Timothy Baldridge wrote: Not really true, most of my programs contain this function: (defn debug [x] (pprint x) x) Now I can do this: (comp foo debug bar) Also, with some reader literal magic, I could write something to let me do this: (myfunc foo #dbg bar) On Thu, May 30, 2013 at 6:12 PM, David Jacobs da...@wit.iojavascript:(mailto: da...@wit.io javascript:) wrote: Two more things: 1) printing is often not a viable option for lazily eval-ed sequences or async processes -- the output gets jumbled! And believe me, when a new Clojure dev sees that for the first time, he/she wants to quit. 2) printing is terrible for elegant clojure code -- thing (comp f g h (partial map z)) -- in order to figure out anything about dynamic data flowing through, you have to break apart that composition or add a let binding in one of those functions before returning a value. Both of those involve a lot of friction. On Thursday, May 30, 2013 5:00:13 PM UTC-7, raould wrote: for a long time haskell did not have a debugger. that sucked, imho. -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript:(mailto: clo...@googlegroups.com javascript:) 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 javascript: (mailto: clojure%2b...@googlegroups.com javascript:) 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 javascript: (mailto: clojure%2b...@googlegroups.com javascript:). For more options, visit https://groups.google.com/groups/opt_out. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript:(mailto: clo...@googlegroups.com javascript:) 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 javascript: (mailto: clojure+u...@googlegroups.com javascript:) 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 javascript: (mailto: clojure+u...@googlegroups.com javascript:). 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Very cool, will have to try it out! That said, I think we should start talking about how to make the traditional debugging cycle accessible in Clojure. On Friday, May 31, 2013 at 8:27 AM, dgrnbrg wrote: I'd like to point out a similar library I wrote for Clojure called spyscope: https://github.com/dgrnbrg/spyscope With spyscope, you can write a handful of characters and get the stack frame, form, and its value pretty-printed and logged to a queue for future querying. On Thursday, May 30, 2013 8:28:19 PM UTC-4, David Jacobs wrote: That's true -- that's why I wrote up the Letters debugging mini-library for Ruby (lettersrb.com (http://lettersrb.com)). However, there's friction there, too, and a surprising number of people don't think to do this. On Thursday, May 30, 2013 at 5:25 PM, Timothy Baldridge wrote: Not really true, most of my programs contain this function: (defn debug [x] (pprint x) x) Now I can do this: (comp foo debug bar) Also, with some reader literal magic, I could write something to let me do this: (myfunc foo #dbg bar) On Thu, May 30, 2013 at 6:12 PM, David Jacobs da...@wit.io (mailto:da...@wit.io) wrote: Two more things: 1) printing is often not a viable option for lazily eval-ed sequences or async processes -- the output gets jumbled! And believe me, when a new Clojure dev sees that for the first time, he/she wants to quit. 2) printing is terrible for elegant clojure code -- thing (comp f g h (partial map z)) -- in order to figure out anything about dynamic data flowing through, you have to break apart that composition or add a let binding in one of those functions before returning a value. Both of those involve a lot of friction. On Thursday, May 30, 2013 5:00:13 PM UTC-7, raould wrote: for a long time haskell did not have a debugger. that sucked, imho. -- -- 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 (mailto: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 (mailto:clojure%2b...@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 (mailto:clojure%2b...@googlegroups.com). For more options, visit https://groups.google.com/groups/opt_out. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- -- 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 (mailto: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 (mailto: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 (mailto: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
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
I'm just catching up on this discussion. I think that, regardless of whether any one coder uses them, debuggers are useful to a large subset of people. Even though Clojure likes us to be immutable, there are often times where we would like to debug the mutable parts of our code with something better than a print statement. (Importantly, it's more efficient to identify a problem spot in code if you can dynamically change what you're interested in as you get feedback from a REPL -- this is something print statements can't do. Print statements often have to be brute-force if you aren't exactly sure what to print.) If we want Clojure to continue to be adopted, we need to support the habits of Web developers. And Web developers expect to: 1. Spot a problem spot in the code 2. Add the word debugger/debug at that spot (or make a breakpoint in an IDE) 3. Make the API call/run the spec/refresh the page/click the button 4. Immediately be in a debugger REPL where they can explore the environment While it doesn't solve all problems, and while the more advanced we are, (perhaps) the sooner we can spot errors without a debugger, the fact is that a debugger is part of the standard workflow for many people. The essential thing is that a debugger quickly loads an execution context into your working memory. Instead of having to think about it for a while, you get immediate feedback about what's going wrong (nesting level is too high, that function doesn't return what you think it does, etc) and can jump into a new codebase easily. So both for adoption and for a quick identify-debug-fix cycle (not all of us can afford hammock time for each and every bug that crops up in the code), I think it's important that we start thinking about creating and documenting debugging tools for the community. Tangent: I don't see any documentation for inserting a debug REPL using Ritz. Anyone have any pointers? Does Ritz actually give me what I described earlier? Best, David On Wednesday, May 29, 2013 8:56:08 AM UTC-7, Ben Mabey wrote: On Wed May 29 09:18:10 2013, Softaddicts wrote: The REPL is a better alternative than a debugger. No REPL available = increase need for a debugger. If you write creepy code in the REPL, you would do the same in a text editor and then end up debugging it in the debugger... with the old fail/edit/build/break to point of failure cycle. It's not the same goals and efficiency. Maybe the following will shed some light. My REPL's main usage is to tinker with my code in a name space until it's resilient and composable as much as possible. I rarely use the REPL to test short snippets. My code is always backed by the name space I am working with. I seldom write unit tests. I make use of pre and post conditions as much as possible to knock the rough edges off. I run integrated tests starting from a root name space (whichever is appropriate for the scope oftest to be done) where I may have to establish some base context. I exercise the code, I can trace/untrace calls, redef fns when needed and so on without restarts. This insures a minimally resilient code base. When a severe error occurs, our logging facility dumps also the environment with all the current bindings in scope where the exception was trapped. We can log bindings up to the top of the call stack... This is usable (as clojure maps) to reconstruct the call context and rerun the culprit chunk of code to pinpoint were are the shortcomings that made it fail. When running full integrated tests, we have access to this data. This is also available from production, we then obtain data to reinject in dev to understand what happened with a limited wiring to establish the global context. We can then reflect this our integrated tests to stress the code. This is more or less easy depending on the code that failed based on how much side effects are impacting the context. The more you use pure fns, the easier it is to rerun failures from the appropriate call site and fix them. The more composable your code is, the less bugs you end up with, fns are smaller, their scope is smaller, ... When I trigger a debugger it's because I hit a strange error from the Clojure compiler that I do not understand upfront or when I deal with interop code and I need to look at the exception and internal states of Java objects in situ. I never need to look at Clojure bindings in the debugger aside from the obscure compilation errors I may hit. I became much more efficient swapping my time spent in a debugger by time spent in the REPL. This is the bottom line and I am convinced from comments I got from colleagues well versed in the use of debuggers that it's not a personal and unique experience. Everyone of them when they saw what can be done in a REPL were
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
for a long time haskell did not have a debugger. that sucked, imho. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Two more things: 1) printing is often not a viable option for lazily eval-ed sequences or async processes -- the output gets jumbled! And believe me, when a new Clojure dev sees that for the first time, he/she wants to quit. 2) printing is terrible for elegant clojure code -- thing (comp f g h (partial map z)) -- in order to figure out anything about dynamic data flowing through, you have to break apart that composition or add a let binding in one of those functions before returning a value. Both of those involve a lot of friction. On Thursday, May 30, 2013 5:00:13 PM UTC-7, raould wrote: for a long time haskell did not have a debugger. that sucked, imho. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Not really true, most of my programs contain this function: (defn debug [x] (pprint x) x) Now I can do this: (comp foo debug bar) Also, with some reader literal magic, I could write something to let me do this: (myfunc foo #dbg bar) On Thu, May 30, 2013 at 6:12 PM, David Jacobs da...@wit.io wrote: Two more things: 1) printing is often not a viable option for lazily eval-ed sequences or async processes -- the output gets jumbled! And believe me, when a new Clojure dev sees that for the first time, he/she wants to quit. 2) printing is terrible for elegant clojure code -- thing (comp f g h (partial map z)) -- in order to figure out anything about dynamic data flowing through, you have to break apart that composition or add a let binding in one of those functions before returning a value. Both of those involve a lot of friction. On Thursday, May 30, 2013 5:00:13 PM UTC-7, raould wrote: for a long time haskell did not have a debugger. that sucked, imho. -- -- 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. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
That's true -- that's why I wrote up the Letters debugging mini-library for Ruby (lettersrb.com). However, there's friction there, too, and a surprising number of people don't think to do this. On Thursday, May 30, 2013 at 5:25 PM, Timothy Baldridge wrote: Not really true, most of my programs contain this function: (defn debug [x] (pprint x) x) Now I can do this: (comp foo debug bar) Also, with some reader literal magic, I could write something to let me do this: (myfunc foo #dbg bar) On Thu, May 30, 2013 at 6:12 PM, David Jacobs da...@wit.io (mailto:da...@wit.io) wrote: Two more things: 1) printing is often not a viable option for lazily eval-ed sequences or async processes -- the output gets jumbled! And believe me, when a new Clojure dev sees that for the first time, he/she wants to quit. 2) printing is terrible for elegant clojure code -- thing (comp f g h (partial map z)) -- in order to figure out anything about dynamic data flowing through, you have to break apart that composition or add a let binding in one of those functions before returning a value. Both of those involve a lot of friction. On Thursday, May 30, 2013 5:00:13 PM UTC-7, raould wrote: for a long time haskell did not have a debugger. that sucked, imho. -- -- 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 (mailto: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 (mailto:clojure%2bunsubscr...@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 (mailto:clojure%2bunsubscr...@googlegroups.com). For more options, visit https://groups.google.com/groups/opt_out. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- -- 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 (mailto: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 (mailto: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 (mailto: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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Warren Lynn wrn.l...@gmail.com writes: Still miss the Elisp debugger, which is great. It's right there, in your editing environment. It's good for debugging my own code. It's really good for working out someone elses code. I wish I debug clojure in the same way. It's not essential, of course. But nice. Phil I miss the Elisp debugger or Common Lisp debugger too. They made fixing an issue so much easier. I think good REPL is a complement (and a very important/good one) to it, not a replacement to it. I don't know if I gained much (or any) if I got a good tool but lost another good one. Yeah, this is exactly what I feel. The elisp debugger is joy because it's right there, in your editing environment and is very first class; although if you are debugging the command loop this is a problem, but in general it's fantastic. I like the test environment in clojure, and although they exist in elisp I never really use them; don't know why, just habit I guess. And yes, in it's absence, I do lean on other tools instead. Still, it would be nice. Phil -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
+1 On 2013-5-29, at 上午2:23, Warren Lynn wrn.l...@gmail.com wrote: Still miss the Elisp debugger, which is great. It's right there, in your editing environment. It's good for debugging my own code. It's really good for working out someone elses code. I wish I debug clojure in the same way. It's not essential, of course. But nice. Phil I miss the Elisp debugger or Common Lisp debugger too. They made fixing an issue so much easier. I think good REPL is a complement (and a very important/good one) to it, not a replacement to it. I don't know if I gained much (or any) if I got a good tool but lost another good one. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
I did not say that a debugger was not useful at all, I said that the importance of having a debugger is *overestimated* especially in an immutable world. Relying on a debugger as an important tool to support coding is like admitting the failure of your code before it runs. It's like conceding defeat before the fight has started. Trying to a avoid debug sessions as much as possible is more productive. Time spent in debug sessions is not spent on more important issues. Luc P. I found this kind of logic hard to swallow. I certainly don't look forward to creating a lot of bugs so I can get the joy of using a debugger. But bugs, sometimes very tricky bugs happen, no matter how good your design is. If you apply the logic that because we can overuse/over rely on it so it is better we don't have it at all we almost don't need anything in the modern life. Following your logic I would argue that if you don't have an REPL, it will force you to think hard and write perfect code that does not need any testing at all. It just runs, because you don't even have a second chance to know what is going on inside and fix it. The quick REPL loop just encourage people to write crappy code and constantly tinker with it (because they know they can easily found out the cause and fix it). Does that sound right to you? We need to get our logic straight before debating this kind of issues. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
The REPL is a better alternative than a debugger. No REPL available = increase need for a debugger. If you write creepy code in the REPL, you would do the same in a text editor and then end up debugging it in the debugger... with the old fail/edit/build/break to point of failure cycle. It's not the same goals and efficiency. Maybe the following will shed some light. My REPL's main usage is to tinker with my code in a name space until it's resilient and composable as much as possible. I rarely use the REPL to test short snippets. My code is always backed by the name space I am working with. I seldom write unit tests. I make use of pre and post conditions as much as possible to knock the rough edges off. I run integrated tests starting from a root name space (whichever is appropriate for the scope oftest to be done) where I may have to establish some base context. I exercise the code, I can trace/untrace calls, redef fns when needed and so on without restarts. This insures a minimally resilient code base. When a severe error occurs, our logging facility dumps also the environment with all the current bindings in scope where the exception was trapped. We can log bindings up to the top of the call stack... This is usable (as clojure maps) to reconstruct the call context and rerun the culprit chunk of code to pinpoint were are the shortcomings that made it fail. When running full integrated tests, we have access to this data. This is also available from production, we then obtain data to reinject in dev to understand what happened with a limited wiring to establish the global context. We can then reflect this our integrated tests to stress the code. This is more or less easy depending on the code that failed based on how much side effects are impacting the context. The more you use pure fns, the easier it is to rerun failures from the appropriate call site and fix them. The more composable your code is, the less bugs you end up with, fns are smaller, their scope is smaller, ... When I trigger a debugger it's because I hit a strange error from the Clojure compiler that I do not understand upfront or when I deal with interop code and I need to look at the exception and internal states of Java objects in situ. I never need to look at Clojure bindings in the debugger aside from the obscure compilation errors I may hit. I became much more efficient swapping my time spent in a debugger by time spent in the REPL. This is the bottom line and I am convinced from comments I got from colleagues well versed in the use of debuggers that it's not a personal and unique experience. Everyone of them when they saw what can be done in a REPL were salivating to the idea of tossing debuggers aside. Luc I did not say that a debugger was not useful at all, I said that the importance of having a debugger is *overestimated* especially in an immutable world. Relying on a debugger as an important tool to support coding is like admitting the failure of your code before it runs. It's like conceding defeat before the fight has started. Trying to a avoid debug sessions as much as possible is more productive. Time spent in debug sessions is not spent on more important issues. Luc P. I found this kind of logic hard to swallow. I certainly don't look forward to creating a lot of bugs so I can get the joy of using a debugger. But bugs, sometimes very tricky bugs happen, no matter how good your design is. If you apply the logic that because we can overuse/over rely on it so it is better we don't have it at all we almost don't need anything in the modern life. Following your logic I would argue that if you don't have an REPL, it will force you to think hard and write perfect code that does not need any testing at all. It just runs, because you don't even have a second chance to know what is going on inside and fix it. The quick REPL loop just encourage people to write crappy code and constantly tinker with it (because they know they can easily found out the cause and fix it). Does that sound right to you? We need to get our logic straight before debating this kind of issues. -- -- 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. -- Softaddictslprefonta...@softaddicts.ca sent by ibisMail
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On Wed May 29 09:18:10 2013, Softaddicts wrote: The REPL is a better alternative than a debugger. No REPL available = increase need for a debugger. If you write creepy code in the REPL, you would do the same in a text editor and then end up debugging it in the debugger... with the old fail/edit/build/break to point of failure cycle. It's not the same goals and efficiency. Maybe the following will shed some light. My REPL's main usage is to tinker with my code in a name space until it's resilient and composable as much as possible. I rarely use the REPL to test short snippets. My code is always backed by the name space I am working with. I seldom write unit tests. I make use of pre and post conditions as much as possible to knock the rough edges off. I run integrated tests starting from a root name space (whichever is appropriate for the scope oftest to be done) where I may have to establish some base context. I exercise the code, I can trace/untrace calls, redef fns when needed and so on without restarts. This insures a minimally resilient code base. When a severe error occurs, our logging facility dumps also the environment with all the current bindings in scope where the exception was trapped. We can log bindings up to the top of the call stack... This is usable (as clojure maps) to reconstruct the call context and rerun the culprit chunk of code to pinpoint were are the shortcomings that made it fail. When running full integrated tests, we have access to this data. This is also available from production, we then obtain data to reinject in dev to understand what happened with a limited wiring to establish the global context. We can then reflect this our integrated tests to stress the code. This is more or less easy depending on the code that failed based on how much side effects are impacting the context. The more you use pure fns, the easier it is to rerun failures from the appropriate call site and fix them. The more composable your code is, the less bugs you end up with, fns are smaller, their scope is smaller, ... When I trigger a debugger it's because I hit a strange error from the Clojure compiler that I do not understand upfront or when I deal with interop code and I need to look at the exception and internal states of Java objects in situ. I never need to look at Clojure bindings in the debugger aside from the obscure compilation errors I may hit. I became much more efficient swapping my time spent in a debugger by time spent in the REPL. This is the bottom line and I am convinced from comments I got from colleagues well versed in the use of debuggers that it's not a personal and unique experience. Everyone of them when they saw what can be done in a REPL were salivating to the idea of tossing debuggers aside. Yes, but a REPL and a debugger are not mutually exclusive. Nice debuggers for dynamic languages give you a REPL at breakpoints with all the context to evaluate expressions against. In other words, why not have your cake and eat it too? :) Clojure has this somewhat with nrepl-ritz evaluation commands (I imagine hooking up an actual repl wouldn't be too hard) and technomany's limit-break[1]. I think what this thread has shown is that a subset of the Clojure community would like better debugger support. Repeated arguments on why they don't need debugger support isn't constructive since this is their personal opinion and development preference. I think this thread has also shown that some people are not aware of the fantastic work Hugo Duncan and others have done for debuggers in Clojure. To help with the awareness issue I think having a clojure-docs tutorial[2] on debugging would go a long ways. As far as getting better support in general perhaps an ambitious member in the community could start a kickstarter to help improve the state of affairs. I know my company would donate to a campaign to improve clojure debuggers. -Ben 1. https://github.com/technomancy/limit-break (I have never gotten limit-break to work for me though.) 2. https://github.com/clojuredocs/cds/issues/27 -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
I'm not sure what your point is. I rely quite a bit on randomly generated tests, and of course, any multithreaded app has nondeterministic elements that can be hard to replicate. For that matter, if you are simply experimenting with new code at the REPL, it might not always be clear what sequence of actions brought about the unique state that caused the problem. Even if it is clear how to recreate the problem, it can be tedious to annotate the code with extra logging info to print out all the local variables, and the mere act of doing so might make the problem go away. There are all sorts of reasons why you'd want to do a fuller investigation of a crash when it happens, using information that was generated directly by the crash, without having to add new code and reconstruct the events leading to the crash. On Mon, May 27, 2013 at 10:53 PM, Cedric Greevey cgree...@gmail.com wrote: You have production code going *boom* that doesn't have any failing tests? Or you have nondeterministic tests? :) -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Oskar Kvist oskar.kv...@gmail.com writes: Stuart Halloway said in his video Clojure in the Field ( http://www.infoq.com/presentations/Clojure-tips) from March 1, 2013 (I think): I don't feel the absence of a debugger because I've learnt enough that I don't ever need a debugger. I am very intrigued by that statement. What does he (or you, if you are reading, Stuart) mean? For me, debugging is the biggest thing that I don't know how to do well currently in Clojure (I use Vim, and have not programmed in Clojure for a while), so I am really interested in what he meant. I'm an emacs head, and that was my originally my first and only experience of lisp. I've really enjoyed learning clojure, and have found it both very useful and very nice. The REPL is great, I eval stuff and play with things. I use test. Still miss the Elisp debugger, which is great. It's right there, in your editing environment. It's good for debugging my own code. It's really good for working out someone elses code. I wish I debug clojure in the same way. It's not essential, of course. But nice. Phil -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
There's not much you can do to retrieve the locals around an exception with adding a Java Agent. REDL is able to get the locals around uses of redl.core/break, since it's a macro and that's an ability of macros. On Monday, May 27, 2013 10:10:39 PM UTC-4, Lee wrote: On May 27, 2013, at 9:54 PM, Softaddicts wrote: Lets take a real life example, [etc.] Debugging was not a viable option. [etc.] This project was extreme in this regard but it prove to me that reviewing code offline and thinking about how to improve it gives much more payback than using the debugger to fix a specific problem. Okay, sometimes debuggers don't help... but sometimes they do! And often it's necessary to step back and think... but sometimes having some key information (like the value of the arguments to my function, or of some other locals, that led to the error) makes the thinking a lot more productive. Elsewhere on this thread: On May 27, 2013, at 9:36 PM, dgrnbrg wrote: For Vim users, I ported the debug repl. This is a tool that allows you to create a REPL in the middle of the call stack, which allows you to suspend the evaluation of functions, lazy seqs, etc, and then inspect the locals and globals at that location. If you've already installed Fireplace, then you just need add the vim plugin and include redl in your project.clj, and use :Repl or :ReplHere to create a repl, and then use redl.core/break and redl.core/continue to use the debugger. You can find the vim component here: https://github.com/dgrnbrg/vim-redl and the Clojure component here: https://github.com/dgrnbrg/redl This sounds pretty neat... but I also don't use Vim. (It's also not completely clear to me from this description if you can get the locals from the context of an error, rather than from a manual suspension.) Is there anything that will provide the values of locals at an error (whether interactively or in a big dump) regardless of the IDE or launch method that one uses? Or if there's nothing that's so general then is there anything that would work from a call to lein run or from Clooj or from Eclipse/CCW? Thanks, -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On May 28, 2013, at 8:43 AM, dgrnbrg wrote: There's not much you can do to retrieve the locals around an exception with adding a Java Agent. REDL is able to get the locals around uses of redl.core/break, since it's a macro and that's an ability of macros. In Common Lisp exceptions are handled in the contexts in which they occur, so if you handle the exception by stopping execution and presenting a REPL (which is the default) then the locals don't have to be retrieved -- they're just still where they were, and where the REPL is too. And there are functions that let you look at locals throughout the stack (graphically browsable in IDEs, but REPL-accessible in any event). I gather that one can't handle exceptions in context like this in Java... but I'm approaching this from the Lisp side and don't really know... I see some related discussions (e.g. in https://news.ycombinator.com/item?id=438125) but it's not clear to me what the bottom line is. If it *is* possible to get this kind of behavior in Clojure than that would be a beautiful thing. -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On May 27, 2013, at 8:31 PM, Charles Harvey III wrote: If you haven't tried out Light Table, it shows you the values of local variables. It is a pretty nice feature. I love the ideas behind LightTable and I check it out from time to time. Checking it out now, though, regarding this issue, I don't see access to locals at the time of an exception. For example: (defn bad [n] (/ 2 n)) (defn bad-caller [x] (bad (- x 3))) (bad-caller 3) I get an exception: java.lang.ArithmeticException: Divide by zero Numbers.java:156 clojure.lang.Numbers.divide Numbers.java:3667 clojure.lang.Numbers.divide NO_SOURCE_FILE:8 ltfoo.core/bad NO_SOURCE_FILE:12 ltfoo.core/bad-caller NO_SOURCE_FILE:16 ltfoo.core/eval4706 but I don't see anywhere the value of n in bad at the time of the exception. -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
This might not be the proper example: If (/ 2 n) throws Divide by zero then n == zero On 28 May 2013 15:40, Lee Spector lspec...@hampshire.edu wrote: On May 27, 2013, at 8:31 PM, Charles Harvey III wrote: If you haven't tried out Light Table, it shows you the values of local variables. It is a pretty nice feature. I love the ideas behind LightTable and I check it out from time to time. Checking it out now, though, regarding this issue, I don't see access to locals at the time of an exception. For example: (defn bad [n] (/ 2 n)) (defn bad-caller [x] (bad (- x 3))) (bad-caller 3) I get an exception: java.lang.ArithmeticException: Divide by zero Numbers.java:156 clojure.lang.Numbers.divide Numbers.java:3667 clojure.lang.Numbers.divide NO_SOURCE_FILE:8 ltfoo.core/bad NO_SOURCE_FILE:12 ltfoo.core/bad-caller NO_SOURCE_FILE:16 ltfoo.core/eval4706 but I don't see anywhere the value of n in bad at the time of the exception. -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On May 28, 2013, at 10:32 AM, Rostislav Svoboda wrote: This might not be the proper example: If (/ 2 n) throws Divide by zero then n == zero Well yes of course it's obvious what the problem is in this case! The point is that if the bad function was more complicated then might help to know what value was passed in as n that led to the error. And in more complicated situations it might help to know what args the caller received as well. And what the values of all of the locals were all the way down the stack. What I was describing was just a test to see if LightTable shows the values that args/locals have when an error occurs, and it looks like it doesn't (at least not right out of the box). -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On Tue, May 28, 2013 at 9:36 AM, Lee Spector lspec...@hampshire.edu wrote: On May 28, 2013, at 8:43 AM, dgrnbrg wrote: There's not much you can do to retrieve the locals around an exception with adding a Java Agent. REDL is able to get the locals around uses of redl.core/break, since it's a macro and that's an ability of macros. In Common Lisp exceptions are handled in the contexts in which they occur, so if you handle the exception by stopping execution and presenting a REPL (which is the default) then the locals don't have to be retrieved -- they're just still where they were, and where the REPL is too. And there are functions that let you look at locals throughout the stack (graphically browsable in IDEs, but REPL-accessible in any event). I gather that one can't handle exceptions in context like this in Java... but I'm approaching this from the Lisp side and don't really know... I see some related discussions (e.g. in https://news.ycombinator.com/item?id=438125) but it's not clear to me what the bottom line is. If it *is* possible to get this kind of behavior in Clojure than that would be a beautiful thing. Eclipse allows setting a breakpoint that triggers on an exception throw, rather than a particular line of code. This implies that the JVM has a debugging hook that allows effectively wrapping every throw with a phantom try...catch to trap that exception and handle it a certain way. So it *should* be possible (with the IDE and debugged code running in separate JVMs) to make a Clojure IDE that can pop you into a REPL at the point of an exception throw (and even to set it to do this only on specific classes of exception). I doubt you could just patch-and-continue like in Common Lisp, though, and it would need further work to be able to examine local variables (and unwind the stack a notch at a time and repeat). I have a general notion of how you might fake some of Common Lisp's functionality: the exception handler creates or recreates a debug namespace, uses more of the JVM's debugging capabilities (which, again, Eclipse can use to let you examine locals when a breakpoint trips) to copy locals into vars of the same names, and binds some var to a function that will set a debug-REPL-triggering breakpoint in the caller one line after the callee returns and then resume, dropping you immediately into the debug REPL again but now in the callee. So you'd end up with something like #java.lang.NullPointerException in foo.core$bar.invoke (core.clj:962) in foo.core$quux.invoke (core.clj:1701) ... In foo.core$bar.invoke (core.clj:962) debug= a 3 debug= b nil ; Aha! Someone called bar with nil. In fact, quux called bar with nil. debug= (unwind) In foo.core$quux.invoke (core.clj:1701) debug= x 0 ; Aha! Should be at least 1. Of course, locals clearing would sometimes mean that information you needed would have been nulled out already. If x had no further use in quux after being passed to bar, for example, it would probably be nil instead of 0, and you'd be limited in what conclusions you could draw from a nil value, unless the local was used farther on. I doubt that's surmountable without reproducing the bug first and then adding a dummy use of the local later than the point of the error so as to keep it from being locals-cleared, but then you might as well just put a println instead of a dummy use there and call it a night. TL;DR: if anything seriously impedes development of a locals-examining debugger capability in a Clojure IDE, it will be locals clearing rather than a lack of capabilities for JVM instrumentation. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Huh. I just solved it. The debug exception handler has to do something a bit fancier, that's all: 1. Dig up the bytecode of the method executing the throw and copy it somewhere. 2. Unwind by one call. 3. Take the bytecode in 1, alter it to wrap the throw site in redl.core/break's macro expansion that captures locals, or something similar, and replacing the offending throw with a direct punt to the debug REPL. 4. Load a class with that as its only method. 5. Invoke that method, with the same arguments as the ... Ah, crap. The arguments might have been locals-cleared by then, in the caller, and by the time of the throw in the callee. Damn damn damn. It would have to recurse farther up the stack and who knows where it would stop? So even with pure functions this enhanced scheme still would only sometimes work -- and with side-effecting ones you have side effects happening twice. I think locals clearing is simply incompatible with ever having full debug info at an error site without anticipation of an error at that site, and with anticipation you can put debug prints, logging, watchers, and suchlike at the site. The lesson for clojure developers being, strive for reproducibility! You should already be using lots of pure functions and few side-effecting ones, and your IDE should keep a REPL history that can be used to reproduce, and perhaps to distill down to a small failing test, any kabooms you get while experimenting in the REPL. And if the domain inherently is going to produce hard-to-reproduce circumstances, invest proactively in aggressive and detailed logging. On Tue, May 28, 2013 at 12:24 PM, Cedric Greevey cgree...@gmail.com wrote: On Tue, May 28, 2013 at 9:36 AM, Lee Spector lspec...@hampshire.eduwrote: On May 28, 2013, at 8:43 AM, dgrnbrg wrote: There's not much you can do to retrieve the locals around an exception with adding a Java Agent. REDL is able to get the locals around uses of redl.core/break, since it's a macro and that's an ability of macros. In Common Lisp exceptions are handled in the contexts in which they occur, so if you handle the exception by stopping execution and presenting a REPL (which is the default) then the locals don't have to be retrieved -- they're just still where they were, and where the REPL is too. And there are functions that let you look at locals throughout the stack (graphically browsable in IDEs, but REPL-accessible in any event). I gather that one can't handle exceptions in context like this in Java... but I'm approaching this from the Lisp side and don't really know... I see some related discussions (e.g. in https://news.ycombinator.com/item?id=438125) but it's not clear to me what the bottom line is. If it *is* possible to get this kind of behavior in Clojure than that would be a beautiful thing. Eclipse allows setting a breakpoint that triggers on an exception throw, rather than a particular line of code. This implies that the JVM has a debugging hook that allows effectively wrapping every throw with a phantom try...catch to trap that exception and handle it a certain way. So it *should* be possible (with the IDE and debugged code running in separate JVMs) to make a Clojure IDE that can pop you into a REPL at the point of an exception throw (and even to set it to do this only on specific classes of exception). I doubt you could just patch-and-continue like in Common Lisp, though, and it would need further work to be able to examine local variables (and unwind the stack a notch at a time and repeat). I have a general notion of how you might fake some of Common Lisp's functionality: the exception handler creates or recreates a debug namespace, uses more of the JVM's debugging capabilities (which, again, Eclipse can use to let you examine locals when a breakpoint trips) to copy locals into vars of the same names, and binds some var to a function that will set a debug-REPL-triggering breakpoint in the caller one line after the callee returns and then resume, dropping you immediately into the debug REPL again but now in the callee. So you'd end up with something like #java.lang.NullPointerException in foo.core$bar.invoke (core.clj:962) in foo.core$quux.invoke (core.clj:1701) ... In foo.core$bar.invoke (core.clj:962) debug= a 3 debug= b nil ; Aha! Someone called bar with nil. In fact, quux called bar with nil. debug= (unwind) In foo.core$quux.invoke (core.clj:1701) debug= x 0 ; Aha! Should be at least 1. Of course, locals clearing would sometimes mean that information you needed would have been nulled out already. If x had no further use in quux after being passed to bar, for example, it would probably be nil instead of 0, and you'd be limited in what conclusions you could draw from a nil value, unless the local was used farther on. I doubt that's surmountable without reproducing the bug first and then adding a dummy use of the local later than the point of the error so as to
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
May I suggest that as useful as your strategies are, they cannot replace a debugger? Let's be clear about our logic before claiming it is not much needed. Maybe YOU really don't need it, but that is different from claiming it is not needed. A debugger as good as it is cannot replace the 4 first strategies. Luc P. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On 5/28/13 10:37 AM, Cedric Greevey wrote: Huh. I just solved it. The debug exception handler has to do something a bit fancier, that's all: 1. Dig up the bytecode of the method executing the throw and copy it somewhere. 2. Unwind by one call. 3. Take the bytecode in 1, alter it to wrap the throw site in redl.core/break's macro expansion that captures locals, or something similar, and replacing the offending throw with a direct punt to the debug REPL. 4. Load a class with that as its only method. 5. Invoke that method, with the same arguments as the ... Ah, crap. The arguments might have been locals-cleared by then, in the caller, and by the time of the throw in the callee. Damn damn damn. It would have to recurse farther up the stack and who knows where it would stop? So even with pure functions this enhanced scheme still would only sometimes work -- and with side-effecting ones you have side effects happening twice. I think locals clearing is simply incompatible with ever having full debug info at an error site without anticipation of an error at that site, and with anticipation you can put debug prints, logging, watchers, and suchlike at the site. You can disable locals clearing with a compiler flag. nrepl-ritz even has helper function that will compile the given form using that flag. If you want to disable locals clearing on a project wide basis you can do so with lein's JVM opts. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On May 28, 2013, at 12:37 PM, Cedric Greevey wrote: I think locals clearing is simply incompatible with ever having full debug info at an error site without anticipation of an error at that site, and with anticipation you can put debug prints, logging, watchers, and suchlike at the site. Too bad, if that's really the final word. It's so very useful to get the locals at the point of (unanticipated) error, and this is information that is already known to the system... and we just want it not to throw it away. The lesson for clojure developers being, strive for reproducibility! You should already be using lots of pure functions and few side-effecting ones, and your IDE should keep a REPL history that can be used to reproduce, and perhaps to distill down to a small failing test, any kabooms you get while experimenting in the REPL. And if the domain inherently is going to produce hard-to-reproduce circumstances, invest proactively in aggressive and detailed logging. My domain (mostly research in evolutionary computation) is indeed inherently going to produce hard-to-reproduce circumstances. And, as it happens, logging that is sufficiently aggressive and detailed logging to capture the things I'll want to see after a crash would produce astronomically (impractically) large log files. It'd be so much nicer just to see the values of the locals at the time of the crash, which are already there in memory if we could only grab them in time. -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
I did a fair amount of programming in C# before switching to Clojure. I noticed an interesting fact: the more lazy (as in using lazy-seqs) and functional my code became, the more erratic the was the flow of execution. It's my personal opinion, that as these features are used more and more in a program, the harder it would be to get any sort of useful information out of a debugger. For instance, look at the implementation of for, map or Clojure's reducers. I'd really hate to step through that code with a debugger. While sometimes I feel a debugger would be nice, I think they are much more useful in imperative languages than they are in functional languages like Clojure. Timothy Baldridge On Tue, May 28, 2013 at 12:05 PM, Warren Lynn wrn.l...@gmail.com wrote: May I suggest that as useful as your strategies are, they cannot replace a debugger? Let's be clear about our logic before claiming it is not much needed. Maybe YOU really don't need it, but that is different from claiming it is not needed. A debugger as good as it is cannot replace the 4 first strategies. Luc P. -- -- 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. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Still miss the Elisp debugger, which is great. It's right there, in your editing environment. It's good for debugging my own code. It's really good for working out someone elses code. I wish I debug clojure in the same way. It's not essential, of course. But nice. Phil I miss the Elisp debugger or Common Lisp debugger too. They made fixing an issue so much easier. I think good REPL is a complement (and a very important/good one) to it, not a replacement to it. I don't know if I gained much (or any) if I got a good tool but lost another good one. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
What about logging aggressively but also aggressively dumping older log entries? Keep only, say, the last 100 or 1000 entries. Something like: (def logger (atom nil)) (def max-log-entries 1000) (def log-file whatever) (defn log [msg] (swap! logger (fn [oldlog] (let [newlog (doall (take max-log-entries (cons msg oldlog)))] (with-open [wr (writer-on log-file)] (binding [*out* wr] (print newlog))) newlog ... (log something interesting happened in foo.core/quux!) ... BOOM! ... ; examine log-file for last 1000 messages produced before the crash NOTE: yeah, there's a side effect in the swap! function. But it's semantically idempotent! Whenever the swap! completes the contents of the file equals the contents of the atom. So it just makes the atom durable. :) On Tue, May 28, 2013 at 2:17 PM, Lee Spector lspec...@hampshire.edu wrote: On May 28, 2013, at 12:37 PM, Cedric Greevey wrote: I think locals clearing is simply incompatible with ever having full debug info at an error site without anticipation of an error at that site, and with anticipation you can put debug prints, logging, watchers, and suchlike at the site. Too bad, if that's really the final word. It's so very useful to get the locals at the point of (unanticipated) error, and this is information that is already known to the system... and we just want it not to throw it away. The lesson for clojure developers being, strive for reproducibility! You should already be using lots of pure functions and few side-effecting ones, and your IDE should keep a REPL history that can be used to reproduce, and perhaps to distill down to a small failing test, any kabooms you get while experimenting in the REPL. And if the domain inherently is going to produce hard-to-reproduce circumstances, invest proactively in aggressive and detailed logging. My domain (mostly research in evolutionary computation) is indeed inherently going to produce hard-to-reproduce circumstances. And, as it happens, logging that is sufficiently aggressive and detailed logging to capture the things I'll want to see after a crash would produce astronomically (impractically) large log files. It'd be so much nicer just to see the values of the locals at the time of the crash, which are already there in memory if we could only grab them in time. -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On 5/28/13 12:19 PM, Lee Spector wrote: On May 28, 2013, at 2:16 PM, Ben Mabey wrote: You can disable locals clearing with a compiler flag. nrepl-ritz even has helper function that will compile the given form using that flag. If you want to disable locals clearing on a project wide basis you can do so with lein's JVM opts. Ooo this sounds promising... I'd love to know how to disable locals clearing for an entire project and then to dump all of the locals on error, if possible... -lee The flag is a system property: -Dclojure.compiler.disable-locals-clearing=true. So you can add that string to your project.clj's :jvm-opts if you are using lein. This will, of course, slow down your program but when I've used it in the past it hasn't made it unusable for development. -Ben -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On May 28, 2013, at 2:16 PM, Ben Mabey wrote: You can disable locals clearing with a compiler flag. nrepl-ritz even has helper function that will compile the given form using that flag. If you want to disable locals clearing on a project wide basis you can do so with lein's JVM opts. Ooo this sounds promising... I'd love to know how to disable locals clearing for an entire project and then to dump all of the locals on error, if possible... -lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On May 28, 2013, at 2:40 PM, Ben Mabey wrote: The flag is a system property: -Dclojure.compiler.disable-locals-clearing=true. So you can add that string to your project.clj's :jvm-opts if you are using lein. This will, of course, slow down your program but when I've used it in the past it hasn't made it unusable for development. Thanks for the project.clj specifics Ben. It still isn't clear to me if/how I could then look at the locals after hitting an unexpected exception. Perhaps Cedric's strategy described a couple of messages back (which I didn't fully understand) would work here? But from the lack of followup to this post http://comments.gmane.org/gmane.comp.java.clojure.swank-clojure.devel/106 -- I wonder if it still won't work when hitting unexpected exceptions. Also, I guess I don't understand what locals clearing is in this context, but why would this slow things down? If it's just preventing the clearing of locals when handling an exception then I'd expect it to have no effect except during an exception... Do you mean that it'll slow down code that does a lot of exception handling in circumstances that aren't really exceptional? Or will this flag do something very different than what I'm thinking, like causing all locals everywhere to be retained forever? That'd cause problems worse than just slowdowns, I would think. -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On 5/28/13 1:05 PM, Lee Spector wrote: On May 28, 2013, at 2:40 PM, Ben Mabey wrote: The flag is a system property: -Dclojure.compiler.disable-locals-clearing=true. So you can add that string to your project.clj's :jvm-opts if you are using lein. This will, of course, slow down your program but when I've used it in the past it hasn't made it unusable for development. Thanks for the project.clj specifics Ben. It still isn't clear to me if/how I could then look at the locals after hitting an unexpected exception. Perhaps Cedric's strategy described a couple of messages back (which I didn't fully understand) would work here? But from the lack of followup to this post http://comments.gmane.org/gmane.comp.java.clojure.swank-clojure.devel/106 -- I wonder if it still won't work when hitting unexpected exceptions. To do this I have been using nrepl-ritz's |'M-x nrepl-ritz-break-on-exception'. If you are using emacs and haven't looked into ritz I would highly encourage taking the time to do so. It is painless to install these days and you can watch a nice presentation on it (https://github.com/pallet/ritz/tree/develop/nrepl#additional-resources). If you aren't using emacs then I don't have any suggestions for you. :( | Also, I guess I don't understand what locals clearing is in this context, but why would this slow things down? If it's just preventing the clearing of locals when handling an exception then I'd expect it to have no effect except during an exception... Do you mean that it'll slow down code that does a lot of exception handling in circumstances that aren't really exceptional? Or will this flag do something very different than what I'm thinking, like causing all locals everywhere to be retained forever? That'd cause problems worse than just slowdowns, I would think. It would slow things down in that more things wouldn't be allowed to be GCed as soon as they would be with locals clearing (the usual culprit being lazy seqs). Unfortunately, I don't know enough of the details of how and when locals clearing works to give you more details. So I'd love to hear a better explanation from someone who knows. -Ben -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
I maintain the strategies summarized by Stuart are a better alternative than repetitive debugging sessions because they change the core of how you are thinking about design and coding, forcing you to have a broader view about how you are doing things and preventing problems before they appear. I came to the same conclusion as Stuart after 30+ years of coding in various languages/assemblers and architectures. Debugger have been in use for more than 35 years and they never improved code quality. They were used to patch specific narrow problems, not avoiding them at the root. I had a colleague once that was writing code in hex directly in the debugger. Nice and exotic but of little value considering that he had to reconstruct source code afterward... and that he'd better not get his mainframe session disconnected while patching his code. I did not say that a debugger was not useful at all, I said that the importance of having a debugger is *overestimated* especially in an immutable world. Relying on a debugger as an important tool to support coding is like admitting the failure of your code before it runs. It's like conceding defeat before the fight has started. Trying to a avoid debug sessions as much as possible is more productive. Time spent in debug sessions is not spent on more important issues. Luc P. May I suggest that as useful as your strategies are, they cannot replace a debugger? Let's be clear about our logic before claiming it is not much needed. Maybe YOU really don't need it, but that is different from claiming it is not needed. A debugger as good as it is cannot replace the 4 first strategies. Luc P. you to -- -- 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. -- Softaddictslprefonta...@softaddicts.ca sent by ibisMail from my ipad! -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On Tuesday, May 28, 2013 1:01:46 PM UTC-7, Ben Mabey wrote: On 5/28/13 1:05 PM, Lee Spector wrote: On May 28, 2013, at 2:40 PM, Ben Mabey wrote: The flag is a system property: -Dclojure.compiler.disable-locals-clearing=true. So you can add that string to your project.clj's :jvm-opts if you are using lein. This will, of course, slow down your program but when I've used it in the past it hasn't made it unusable for development. Thanks for the project.clj specifics Ben. It still isn't clear to me if/how I could then look at the locals after hitting an unexpected exception. Perhaps Cedric's strategy described a couple of messages back (which I didn't fully understand) would work here? But from the lack of followup to this post http://comments.gmane.org/gmane.comp.java.clojure.swank-clojure.devel/106 -- I wonder if it still won't work when hitting unexpected exceptions. To do this I have been using nrepl-ritz's 'M-x nrepl-ritz-break-on-exception'. If you are using emacs and haven't looked into ritz I would highly encourage taking the time to do so. It is painless to install these days and you can watch a nice presentation on it ( https://github.com/pallet/ritz/tree/develop/nrepl#additional-resources). If you aren't using emacs then I don't have any suggestions for you. :( Also, I guess I don't understand what locals clearing is in this context, but why would this slow things down? If it's just preventing the clearing of locals when handling an exception then I'd expect it to have no effect except during an exception... Do you mean that it'll slow down code that does a lot of exception handling in circumstances that aren't really exceptional? Or will this flag do something very different than what I'm thinking, like causing all locals everywhere to be retained forever? That'd cause problems worse than just slowdowns, I would think. It would slow things down in that more things wouldn't be allowed to be GCed as soon as they would be with locals clearing (the usual culprit being lazy seqs). Unfortunately, I don't know enough of the details of how and when locals clearing works to give you more details. So I'd love to hear a better explanation from someone who knows. The principal problem of disabling locals-clearing is not slowing things down, but rather causing perfectly reasonable code to consume unbounded memory. For example, consider: ((fn [xs] (nth xs 1e8)) (range)). With locals clearing, the compiler makes sure that xs is available for GC as it is being processed, so that the working-set size is small. If locals clearing is disabled, the local reference xs is kept around in case a debugger wants to look at it, and so the head of xs is being held while it is realized, meaning a hundred-million-element range must be kept in memory until the function call completes. It's definitely useful to be able to disable locals-clearing temporarily while debugging, but doing so in any kind of production app would be a disaster. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
And, of course, Engelberg's objection then applies again: you have to have the bug, disable locals clearing, and then try to reproduce the bug again in order to have the otherwise-cleared locals available in the debug session. Clojure just doesn't make what he asked for easy, by its nature. Designing to minimize difficulty with reproducing any observed behavior seems to be indicated (and desirable for other reasons anyway). On Tue, May 28, 2013 at 5:10 PM, Alan Malloy a...@malloys.org wrote: On Tuesday, May 28, 2013 1:01:46 PM UTC-7, Ben Mabey wrote: On 5/28/13 1:05 PM, Lee Spector wrote: On May 28, 2013, at 2:40 PM, Ben Mabey wrote: The flag is a system property: -Dclojure.compiler.disable-**locals-clearing=true. So you can add that string to your project.clj's :jvm-opts if you are using lein. This will, of course, slow down your program but when I've used it in the past it hasn't made it unusable for development. Thanks for the project.clj specifics Ben. It still isn't clear to me if/how I could then look at the locals after hitting an unexpected exception. Perhaps Cedric's strategy described a couple of messages back (which I didn't fully understand) would work here? But from the lack of followup to this post http://comments.gmane.org/**gmane.comp.java.clojure.swank-**clojure.devel/106 http://comments.gmane.org/gmane.comp.java.clojure.swank-clojure.devel/106 -- I wonder if it still won't work when hitting unexpected exceptions. To do this I have been using nrepl-ritz's 'M-x nrepl-ritz-break-on-exception'**. If you are using emacs and haven't looked into ritz I would highly encourage taking the time to do so. It is painless to install these days and you can watch a nice presentation on it ( https://github.com/pallet/**ritz/tree/develop/nrepl#** additional-resourceshttps://github.com/pallet/ritz/tree/develop/nrepl#additional-resources). If you aren't using emacs then I don't have any suggestions for you. :( Also, I guess I don't understand what locals clearing is in this context, but why would this slow things down? If it's just preventing the clearing of locals when handling an exception then I'd expect it to have no effect except during an exception... Do you mean that it'll slow down code that does a lot of exception handling in circumstances that aren't really exceptional? Or will this flag do something very different than what I'm thinking, like causing all locals everywhere to be retained forever? That'd cause problems worse than just slowdowns, I would think. It would slow things down in that more things wouldn't be allowed to be GCed as soon as they would be with locals clearing (the usual culprit being lazy seqs). Unfortunately, I don't know enough of the details of how and when locals clearing works to give you more details. So I'd love to hear a better explanation from someone who knows. The principal problem of disabling locals-clearing is not slowing things down, but rather causing perfectly reasonable code to consume unbounded memory. For example, consider: ((fn [xs] (nth xs 1e8)) (range)). With locals clearing, the compiler makes sure that xs is available for GC as it is being processed, so that the working-set size is small. If locals clearing is disabled, the local reference xs is kept around in case a debugger wants to look at it, and so the head of xs is being held while it is realized, meaning a hundred-million-element range must be kept in memory until the function call completes. It's definitely useful to be able to disable locals-clearing temporarily while debugging, but doing so in any kind of production app would be a disaster. -- -- 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
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On Tue, May 28, 2013 at 1:35 PM, Softaddicts lprefonta...@softaddicts.ca wrote: I came to the same conclusion as Stuart after 30+ years of coding in various languages/assemblers and architectures. Interesting thread and I find myself in agreement with Luc here. I've been programming commercially for about 30 years and I used a step debugger back in the day with C and later C++ code but found myself relying on it less and less over the years. I've used the step debugger maybe three times with Clojure in the last three years, and two of those occasions were more to see where the state of the art was at, out of curiosity. I've hardly used step debuggers at all for the last 15 years, since I moved to the JVM. Every now and then, I've found a debugger to be very useful, but with the complexity of a lot of software workflows these days, trying to hit the right breakpoints, and step thru just the critical parts of the system, has become increasingly difficult, compared to just adding tracing or logging at various points. Mark's original point is well-made: the biggest bang for our buck is likely to come from exceptions being able to capture and automatically display all of the in-scope vars at the point of failure. Even with a step debugger, you still have to reproduce the failure, often repeatedly, slowly zeroing in on the correct breakpoints in order to analyze what caused it. The Ritz debugger, with the ability to break on exception and display locals (if you've disabled locals clearing), can be very helpful here but you still have to repro the failure - which as several folks have said, is not at all easy in a complex and/or non-deterministic system. Worse, if the failure arises from bad data - or the failure is simply incorrect results - then breaking on an exception won't help you anyway, and you're back to painstakingly tracking thru code to find where data went bad. Hammock time, careful human analysis, and selective logging and tracing is more likely to yield results quicker for less effort, in my opinion. As is a comprehensive test suite :) -- Sean A Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ World Singles, LLC. -- http://worldsingles.com/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On May 28, 2013, at 5:10 PM, Alan Malloy wrote: The principal problem of disabling locals-clearing is not slowing things down, but rather causing perfectly reasonable code to consume unbounded memory. For example, consider: ((fn [xs] (nth xs 1e8)) (range)). With locals clearing, the compiler makes sure that xs is available for GC as it is being processed, so that the working-set size is small. If locals clearing is disabled, the local reference xs is kept around in case a debugger wants to look at it, and so the head of xs is being held while it is realized, meaning a hundred-million-element range must be kept in memory until the function call completes. It's definitely useful to be able to disable locals-clearing temporarily while debugging, but doing so in any kind of production app would be a disaster. Shouldn't it be possible, at least in principle, to retain only those things that could be referenced at the point of the error? In other words, if you can GC it under normal circumstances then go ahead and GC it. If you can't, then don't (of course), and when we hit an exception then we want to be able to see whatever is still around (or if that's hard for tails of lazy sequences or for any other reason, then punt on this stuff). I obviously don't know the guts of the JVM, but I think that something like this is what's wanted. -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
A couple more replies to comments on this thread: On May 28, 2013, at 5:50 PM, Cedric Greevey wrote: Clojure just doesn't make what he asked for easy, by its nature. Designing to minimize difficulty with reproducing any observed behavior seems to be indicated (and desirable for other reasons anyway). Sure, but in some kinds/styles of work this is more inconvenient / inappropriate than in others. On May 28, 2013, at 6:08 PM, Sean Corfield wrote: Mark's original point is well-made: the biggest bang for our buck is likely to come from exceptions being able to capture and automatically display all of the in-scope vars at the point of failure. Even with a step debugger, you still have to reproduce the failure, often [etc] I agree 100% with Sean and Mark that, from my perspective, the best thing to shoot for is some kind of display of locals at the point of an error. This was always crucial to me in Common Lisp (I never much used the stepper or the snazzy restart mechanism) and its absence in Clojure has been one of the main pain points of my transition to Clojure. I think this is true of my work as a programmer/researcher but also as a teacher; when something breaks, which is all the time with new programmers, you want to be able to look around and see what the state was that caused the error. You really want to see the values of locals, and in Common Lisp that was easy and obvious, while in Clojure it seems to be close to impossible. It looks from Hugo's video like I can get this kind of functionality now if I run my code via emacs and use nrepl-ritz... although it sounds like this can lead to memory management problems, so that one shouldn't do it routinely (and plus I generally want to run my code in other ways). So, not optimal but a start. If there was a way to get locals to be displayed on error, without the restriction to emacs and without the performance issues, then I think that would be a big win for a lot of people. -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
One technique I've used in the past for debugging is to open a UDP port as a log stream and print messages to that stream. These messages can be read at any time by a telnet connection to that port. Since UDP packets that are not read just get dropped this is equivalent to writing to /dev/null except when you want to watch what is begin logged. Since the values are printed they don't have to be kept. You can even keep this live in a production environment for dumping things like statistics. At Worldcom I used this to put up a live console. It might be possible to make a DEFTRACE macro to replace the DEFN which prints the arguments and return values to the UDP port as in enter (FOO asdf 3 'thing) exit (FOO 6) When you connect to the UPD port you'll see an active trace, including the arguments. If you set up a netcat listener on the port you can dump the stream to a file and see the execution. If you're really slick you can open a slime-like port to dump the trace to an emacs buffer. Tim Daly -- -- 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.
I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Stuart Halloway said in his video Clojure in the Field ( http://www.infoq.com/presentations/Clojure-tips) from March 1, 2013 (I think): I don't feel the absence of a debugger because I've learnt enough that I don't ever need a debugger. I am very intrigued by that statement. What does he (or you, if you are reading, Stuart) mean? For me, debugging is the biggest thing that I don't know how to do well currently in Clojure (I use Vim, and have not programmed in Clojure for a while), so I am really interested in what he meant. And by the way: As I said, I have not been using Clojure for a few months, but: What's the state of the art of debugging for Vim users? I've been meaning to try out vim-fireplace and ritz and see if they work together well, but have not gotten around to it yet. I would very much appreciate a nudge in the right direction. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
I just watched that video and interpreted it to mean that of the many strategies available to understand problematic behavior in a live app: * reading the code offline + sufficient hammock time * reproducing the problem offline using test cases in an appropriate simulation environment * appropriate logging and tracing at runtime * repl into the live app * tool-assisted stepwise execution and runtime examination (debugging) He's able to be sufficiently productive using the first 4 strategies and doesn't miss the 5th. In that video he also clarified that his recent experience in the field with clojure has been with datomic, of which he and Rich are probably the principal authors, so it's familiar code, with test cases and the logging and tracing he wants. He usually responds very quickly to bug reports on the datomic list, often within hours, so in that case it's fair to say that he's not being hampered by the absence of a debugger. I've found debuggers are most useful in cases where: * the code is unfamiliar/source is unavailable * there isn't an appropriate staging environment or test harness * there aren't good logs * there's no repl However, in a language like clojure, a live repl can fill the role (and then some) of a debugger. I personally can't speak to vim integration, don't use it with clojure. On Mon, May 27, 2013 at 2:34 PM, Oskar Kvist oskar.kv...@gmail.com wrote: Stuart Halloway said in his video Clojure in the Field ( http://www.infoq.com/presentations/Clojure-tips) from March 1, 2013 (I think): I don't feel the absence of a debugger because I've learnt enough that I don't ever need a debugger. I am very intrigued by that statement. What does he (or you, if you are reading, Stuart) mean? For me, debugging is the biggest thing that I don't know how to do well currently in Clojure (I use Vim, and have not programmed in Clojure for a while), so I am really interested in what he meant. And by the way: As I said, I have not been using Clojure for a few months, but: What's the state of the art of debugging for Vim users? I've been meaning to try out vim-fireplace and ritz and see if they work together well, but have not gotten around to it yet. I would very much appreciate a nudge in the right direction. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Stuart Halloway said in his video Clojure in the Field ( http://www.infoq.com/presentations/Clojure-tips) from March 1, 2013 (I think): I don't feel the absence of a debugger because I've learnt enough that I don't ever need a debugger. I am very intrigued by that statement. What does he (or you, if you are reading, Stuart) mean? For me, debugging is the biggest thing that I don't know how to do well currently in Clojure (I use Vim, and have not programmed in Clojure for a while), so I am really interested in what he meant. Like Stuart, I haven't used a debugger in years. I find that debuggers give me something to do with my hands while thinking about the failure. They used to be very useful on slow machines but these billion-instructions-per-second toys we have now just tend to overwhelm with data. Try navel debugging. Write a few lines of code, rebuild the system, test that it works the way you expect. If it fails the failure is almost certainly in the changes you just made. Sit back, contemplate your navel, stare at the code, and the nature of the bug will likely reveal itself. Most likely the bug is in the piece of code you don't understand. Of course, this won't work well when working with other people's code. Finding those bugs usually requires human to human communication. 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. Is it possible to dynamically swap a Clojure function definition with a trace function? You would have to interpret the tracer's code fragments in the lexical environment of the call. Are environments first class objects in Clojure? How would that work in an STM code block? How do you stack smash an immutable data structure and continue execution from the breakpoint? How would you mutate a value in the caller's environment? Tim -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Doesn't ritz support nrepl? http://github.com/pallet/ritz On Mon, May 27, 2013 at 5:53 PM, Mark Engelberg mark.engelb...@gmail.comwrote: I would be a lot happier with the state of Clojure debugging if, in addition to a stacktrace, I could easily explore the local variables in play when an error was triggered. It was possible to do this in earlier Clojure environments, but the capability seems to have been lost in the transition to nrepl. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Yes and no. nrepl ritz lags behind slime, especially in areas such as breakpoints and inspection. On Mon, May 27, 2013 at 3:22 PM, David Nolen dnolen.li...@gmail.com wrote: Doesn't ritz support nrepl? http://github.com/pallet/ritz On Mon, May 27, 2013 at 5:53 PM, Mark Engelberg mark.engelb...@gmail.comwrote: I would be a lot happier with the state of Clojure debugging if, in addition to a stacktrace, I could easily explore the local variables in play when an error was triggered. It was possible to do this in earlier Clojure environments, but the capability seems to have been lost in the transition to nrepl. -- -- 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. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
I use Eclipse and rarely use the debugger. When I use the debugger it's mainly in some interop situations where I need to look at both sides of the fence, Java and Clojure at the same time. Most of the time it's a misuse of the API that triggers exceptions. These first four strategies are both covering 98% of the needs and reflect sane priorities. Reading the code offline and hammock time is of the utmost importance. If you get stuck in a dead end with some obscure bug, it's a sign that you need this time to reassess your understanding and design of your code. Think about others trying to understand your code if you cannot keep your own code under control... It may well be a sign that it needs some improvements to make it more resilient and cleaner. I frequently used a debugger in the past when integrating component written in different languages because most of the time it's the only easy way to bridge the gap between them (different call conventions, runtimes, call side effects, ...). There are lot less side effects in Clojure, it makes the added value of a debugger limited in a Clojure centric app. The importance of having a debugger is highly exaggerated in this context. A debugger as good as it is cannot replace the 4 first strategies. Luc P. I just watched that video and interpreted it to mean that of the many strategies available to understand problematic behavior in a live app: * reading the code offline + sufficient hammock time * reproducing the problem offline using test cases in an appropriate simulation environment * appropriate logging and tracing at runtime * repl into the live app * tool-assisted stepwise execution and runtime examination (debugging) He's able to be sufficiently productive using the first 4 strategies and doesn't miss the 5th. In that video he also clarified that his recent experience in the field with clojure has been with datomic, of which he and Rich are probably the principal authors, so it's familiar code, with test cases and the logging and tracing he wants. He usually responds very quickly to bug reports on the datomic list, often within hours, so in that case it's fair to say that he's not being hampered by the absence of a debugger. I've found debuggers are most useful in cases where: * the code is unfamiliar/source is unavailable * there isn't an appropriate staging environment or test harness * there aren't good logs * there's no repl However, in a language like clojure, a live repl can fill the role (and then some) of a debugger. I personally can't speak to vim integration, don't use it with clojure. On Mon, May 27, 2013 at 2:34 PM, Oskar Kvist oskar.kv...@gmail.com wrote: Stuart Halloway said in his video Clojure in the Field ( http://www.infoq.com/presentations/Clojure-tips) from March 1, 2013 (I think): I don't feel the absence of a debugger because I've learnt enough that I don't ever need a debugger. I am very intrigued by that statement. What does he (or you, if you are reading, Stuart) mean? For me, debugging is the biggest thing that I don't know how to do well currently in Clojure (I use Vim, and have not programmed in Clojure for a while), so I am really interested in what he meant. And by the way: As I said, I have not been using Clojure for a few months, but: What's the state of the art of debugging for Vim users? I've been meaning to try out vim-fireplace and ritz and see if they work together well, but have not gotten around to it yet. I would very much appreciate a nudge in the right direction. -- -- 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
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Coming from Visual Studio all those years ago, I deeply missed my debugger. These days, I miss my debugger extremely rarely. And when I do use a debugger, I much prefer a non-visual one: Either something like dgb, or something like a hypothetical open-repl-here function, where I can ask specific questions and get specific answers... logged to my terminal! I find that trace points (aka print statements) are more useful than break points because I can look at cross sections of execution (read: logs) rather than specific instruction pointer locations. And when you get a log in your terminal, you spend less time re-asking and re-evaluating by hovering your mouse around, which is quick to confuse you. Logs are particularly useful with pretty printed Clojure data, since you know the values have remained immutable since you have printed them! Most of the time, stepping through code is just much slower than thinking, inserting a precise print statement, and then re-executing the broken code. However, this means that you need to design your code for determinism, repeatability, and visibility. So not having a debugger means also has pleasant affects on your design! On Monday, May 27, 2013 2:34:23 PM UTC-4, Oskar Kvist wrote: Stuart Halloway said in his video Clojure in the Field ( http://www.infoq.com/presentations/Clojure-tips) from March 1, 2013 (I think): I don't feel the absence of a debugger because I've learnt enough that I don't ever need a debugger. I am very intrigued by that statement. What does he (or you, if you are reading, Stuart) mean? For me, debugging is the biggest thing that I don't know how to do well currently in Clojure (I use Vim, and have not programmed in Clojure for a while), so I am really interested in what he meant. And by the way: As I said, I have not been using Clojure for a few months, but: What's the state of the art of debugging for Vim users? I've been meaning to try out vim-fireplace and ritz and see if they work together well, but have not gotten around to it yet. I would very much appreciate a nudge in the right direction. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On May 27, 2013, at 5:53 PM, Mark Engelberg wrote: I would be a lot happier with the state of Clojure debugging if, in addition to a stacktrace, I could easily explore the local variables in play when an error was triggered. It was possible to do this in earlier Clojure environments, but the capability seems to have been lost in the transition to nrepl. This is also the main debugging feature I want and don't have in any of the ways that I currently work with Clojure. I've seen montion of libraries that one can include that will give one this kind of functionality, but I've never gotten anything to work. Does anyone know a simple way to do this that doesn't involve an Emacs-based tool set? In my former life in Common Lisp I think that every environment -- from command-line-based implementations to full-featured IDEs -- would put you in a REPL at the point of an error, from which you could examine locals all the way up the stack, evaluate expressions, and even redefine things and continue. I don't usually need all of this, but it seems cruel for the system to be throwing away all of that stack info (local variables) that I often know contains the information I need to track down and fix a bug. Later in the thread: On May 27, 2013, at 8:17 PM, Brandon Bloom wrote: Most of the time, stepping through code is just much slower than thinking, inserting a precise print statement, and then re-executing the broken code. However, this means that you need to design your code for determinism, repeatability, and visibility. So not having a debugger means also has pleasant affects on your design! Most of my code is intentionally and intrinsically non-deterministic, and re-executing can take days. So it sure would be nice to be able to see the locals that were in play when the error was triggered! -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
For Vim users, I ported the debug repl. This is a tool that allows you to create a REPL in the middle of the call stack, which allows you to suspend the evaluation of functions, lazy seqs, etc, and then inspect the locals and globals at that location. If you've already installed Fireplace, then you just need add the vim plugin and include redl in your project.clj, and use :Repl or :ReplHere to create a repl, and then use redl.core/break and redl.core/continue to use the debugger. You can find the vim component here: https://github.com/dgrnbrg/vim-redl and the Clojure component here: https://github.com/dgrnbrg/redl Let me know if you need help setting it up! On Monday, May 27, 2013 2:34:23 PM UTC-4, Oskar Kvist wrote: Stuart Halloway said in his video Clojure in the Field ( http://www.infoq.com/presentations/Clojure-tips) from March 1, 2013 (I think): I don't feel the absence of a debugger because I've learnt enough that I don't ever need a debugger. I am very intrigued by that statement. What does he (or you, if you are reading, Stuart) mean? For me, debugging is the biggest thing that I don't know how to do well currently in Clojure (I use Vim, and have not programmed in Clojure for a while), so I am really interested in what he meant. And by the way: As I said, I have not been using Clojure for a few months, but: What's the state of the art of debugging for Vim users? I've been meaning to try out vim-fireplace and ritz and see if they work together well, but have not gotten around to it yet. I would very much appreciate a nudge in the right direction. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
Lets take a real life example, I had to design a backup system to take over when a master quote feed made of several individual feeds failed. My backup system had access to same raw feeds as the master system using serial lines but there were no guarantee that both systems would receive the raw feeds within the same time slot. I had to sort out messages while listening to the master feed to replicate the same orderly message stream as the master while avoiding sending duplicates. This was highly non deterministic, I ended up with more than two dozen threads with circular buffers, etc... with obviously mutation everywhere, mutexes, condition variables, ... to try to stay in sync with the master feed. Tests had to be done with real data which of course changed every time I had to test. Add to this an unstable Solaris kernel thread subsystem. Took three weeks to find the proper patch mix to attain the nirvana of stability. Debugging was not a viable option. The only options were code review/hammock time and sufficient logging. This was written in C, no REPL, the old fail/fix/compile/link/run cycle. This project was extreme in this regard but it prove to me that reviewing code offline and thinking about how to improve it gives much more payback than using the debugger to fix a specific problem. Luc P. On May 27, 2013, at 5:53 PM, Mark Engelberg wrote: I would be a lot happier with the state of Clojure debugging if, in addition to a stacktrace, I could easily explore the local variables in play when an error was triggered. It was possible to do this in earlier Clojure environments, but the capability seems to have been lost in the transition to nrepl. This is also the main debugging feature I want and don't have in any of the ways that I currently work with Clojure. I've seen montion of libraries that one can include that will give one this kind of functionality, but I've never gotten anything to work. Does anyone know a simple way to do this that doesn't involve an Emacs-based tool set? In my former life in Common Lisp I think that every environment -- from command-line-based implementations to full-featured IDEs -- would put you in a REPL at the point of an error, from which you could examine locals all the way up the stack, evaluate expressions, and even redefine things and continue. I don't usually need all of this, but it seems cruel for the system to be throwing away all of that stack info (local variables) that I often know contains the information I need to track down and fix a bug. Later in the thread: On May 27, 2013, at 8:17 PM, Brandon Bloom wrote: Most of the time, stepping through code is just much slower than thinking, inserting a precise print statement, and then re-executing the broken code. However, this means that you need to design your code for determinism, repeatability, and visibility. So not having a debugger means also has pleasant affects on your design! Most of my code is intentionally and intrinsically non-deterministic, and re-executing can take days. So it sure would be nice to be able to see the locals that were in play when the error was triggered! -Lee -- -- 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. -- Softaddictslprefonta...@softaddicts.ca sent by ibisMail from my ipad! -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On May 27, 2013, at 9:54 PM, Softaddicts wrote: Lets take a real life example, [etc.] Debugging was not a viable option. [etc.] This project was extreme in this regard but it prove to me that reviewing code offline and thinking about how to improve it gives much more payback than using the debugger to fix a specific problem. Okay, sometimes debuggers don't help... but sometimes they do! And often it's necessary to step back and think... but sometimes having some key information (like the value of the arguments to my function, or of some other locals, that led to the error) makes the thinking a lot more productive. Elsewhere on this thread: On May 27, 2013, at 9:36 PM, dgrnbrg wrote: For Vim users, I ported the debug repl. This is a tool that allows you to create a REPL in the middle of the call stack, which allows you to suspend the evaluation of functions, lazy seqs, etc, and then inspect the locals and globals at that location. If you've already installed Fireplace, then you just need add the vim plugin and include redl in your project.clj, and use :Repl or :ReplHere to create a repl, and then use redl.core/break and redl.core/continue to use the debugger. You can find the vim component here: https://github.com/dgrnbrg/vim-redl and the Clojure component here: https://github.com/dgrnbrg/redl This sounds pretty neat... but I also don't use Vim. (It's also not completely clear to me from this description if you can get the locals from the context of an error, rather than from a manual suspension.) Is there anything that will provide the values of locals at an error (whether interactively or in a big dump) regardless of the IDE or launch method that one uses? Or if there's nothing that's so general then is there anything that would work from a call to lein run or from Clooj or from Eclipse/CCW? Thanks, -Lee -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
If you haven't tried out Light Table, it shows you the values of local variables. It is a pretty nice feature. On Monday, May 27, 2013 5:53:16 PM UTC-4, puzzler wrote: I would be a lot happier with the state of Clojure debugging if, in addition to a stacktrace, I could easily explore the local variables in play when an error was triggered. It was possible to do this in earlier Clojure environments, but the capability seems to have been lost in the transition to nrepl. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
On Mon, May 27, 2013 at 10:25 PM, Cedric Greevey cgree...@gmail.com wrote: 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. You've just listed three things that I can *add* to my code to track down errors: watches, logging, pre clauses (and let's not forget the old standby printf). But that all misses the point. When my code goes *boom* and I get an error and a stacktrace, I want to know specifically what the context was at the time of *that particular crash*. If I have to alter my code and rerun, it may be hard to recreate the conditions that caused the error. If the stacktrace simply revealed richer information, such as what the inputs were to the various functions in the stacktrace, and I could explore the local variables, that would save tons of time spent trying to annotate the function to print or log the variables and then trying to get the bug to happen again. -- -- 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.
Re: I don't feel the absence of a debugger, because I've learnt enough that I don't ever need a debugger.
You have production code going *boom* that doesn't have any failing tests? Or you have nondeterministic tests? :) On Tue, May 28, 2013 at 1:49 AM, Mark Engelberg mark.engelb...@gmail.comwrote: On Mon, May 27, 2013 at 10:25 PM, Cedric Greevey cgree...@gmail.comwrote: 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. You've just listed three things that I can *add* to my code to track down errors: watches, logging, pre clauses (and let's not forget the old standby printf). But that all misses the point. When my code goes *boom* and I get an error and a stacktrace, I want to know specifically what the context was at the time of *that particular crash*. If I have to alter my code and rerun, it may be hard to recreate the conditions that caused the error. If the stacktrace simply revealed richer information, such as what the inputs were to the various functions in the stacktrace, and I could explore the local variables, that would save tons of time spent trying to annotate the function to print or log the variables and then trying to get the bug to happen again. -- -- 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.