On Sat, Jul 2, 2011 at 8:19 PM, Luc Prefontaine <lprefonta...@softaddicts.ca> wrote: > Were did you find the link between functional languages and close proximity of > errors ? That's a language design decision. You may want to use assertions > on your fns to validate inputs. That sould improve your ability to track > errors > before they carry things too far from the spotwhere it failed. > I would not trade this for systematic exception reporting.
Sorry if I wasn't clear about this. One time I was rereading a book about the art of debugging (I think it was this book: http://www.amazon.com/Why-Programs-Fail-Second-Systematic/dp/0123745152), and realized that the main theme of the book is that the #1 reason that debugging is hard is that most bugs result from some sort of mutation of state in one part of your code that inadvertently violates some assumption or invariant you had in your mind. But your program doesn't crash right away, it keeps quietly chugging along with that corrupted state until some completely separate portion of your program tries to do something with that data that no longer makes sense and KA-BOOM. But the line your debugger shows you just shows you where the crash happened; it can't show you the series of steps that led to the corruption of state that actually caused the crash. Thus, you need to do a lot of detective work and step through the program. This is precisely why, for example, most programmers will gladly pay the performance penalty for bounds-checking on array reads and writes -- it's incredibly valuable to have your program crash where the problem actually occurs, rather than continuing for a while with spurious values or corrupted memory and getting a delayed crash with no clear connection to the cause. I had a personal a-ha moment when I read that, which made me realize that one of the reasons I enjoy functional programming so much more is that this class of bug just doesn't happen. Generally speaking, crashes have good locality with respect to the flaw in the code that causes them because there's no "state" to get corrupted and eventually cause a delayed crash. Of course, often the hardest bugs of all to find are the ones that are the result of deep logical flaws. The program may be an exact implementation of what you had in mind, but what you had in mind doesn't quite accomplish what you expected it to. And that's the problem I have with some of Clojure's core functions -- they can turn a blatant mismatch (between a function's input requirements and the inputs that actually get passed) into a deep logical flaw. The get example I raised is a perfect example of this. When I passed a transient set to a function that used get, I reasonably assumed that transient sets implement whatever interface get requires. But rather than raise an error because the object didn't support the desired interface, get just returned nil -- which is the exact same value that is returned in ordinary usage when you test whether something is in the set and it isn't! So now, I have sets that are quietly being passed around, and returning sensible values but behaving as if they don't have any elements. What should be an easy bug has turned into a deep logical flaw in my program. Everything appears to be working, but my program generates completely bogus outputs because at some stage of its processing it tested for membership in a set and got back nil for something that was actually in the set. This is the kind of thing that is a real nuisance to track down, requiring detailed detective work and a careful analysis of the entire chain of logic to find the spot where things actually go wrong. Given that get creates the illusion of working even when it doesn't, I fail to see how a pre or post condition in my own code could have picked up on this or validated the input, short of having a deep understanding of all the interfaces required by every core function and testing every input explicitly for support of those interfaces (in which case, I might as well be using a statically typed language). -- 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