Thank you, Ken. It's encouraging to see the community is thinking of ways to improve this.
On Aug 2, 6:39 am, Ken Wesson <kwess...@gmail.com> wrote: > On Tue, Aug 2, 2011 at 3:11 AM, recurve7 <dan.m...@gmail.com> wrote: > > Here's one example where recursion and lack of positional error > > feedback make it hard for me, as someone coming from Java, to spot the > > error (and seeing "ClassCastException" threw me off and had me > > wondering where/how I had done something like that): > > > user=> (defn fac [n] (if (= n 1) 1 (* n fac (- n 1)))) > > #'user/fac > > user=> (fac 3) > > java.lang.ClassCastException: user$fac cannot be cast to > > java.lang.Number (NO_SOURCE_FILE:0) > > This is saying that a "user$fac" was found where a number was > expected. You have a function called fac in the user namespace -- this > is "user$fac" to Java. So, you probably tried to perform arithmetic on > a function. It's a math function, so you probably meant to call it and > perform arithmetic on the result, and left out a pair of parentheses. > > It is true that the messages commonly encountered could stand to be > better documented on a Clojure site. I'm wondering if we could go > further, though, and make REPL exception printing more informative. > The Java exception gets stored in *e, so someone can always type *e to > retrieve it, or (.printStackTrace *e), etc., so printing an > interpretation of the exception wouldn't render the raw exception > inaccessible. > > This suggests trying to parse common exceptions into Clojurish > messages; e.g. the above could be found to be a CCE, then the detail > message parsed to extract the classnames; then a message pieced > together based on those, e.g. > > java.lang.Number -> a number > clojure.lang.Cons/LazySeq/PersistentList/etc. -> a list or seq > clojure.lang.Vector -> a vector > w.x$y when a function w.x/y exists -> the function w.x/y > ... > > and the shallowest Clojure function before interop can be dug out of > the stack trace, in the above case clojure.core/*, and the above > message could then come out as > > Error: expected a number for *, but found the function user/fac instead. > > In the case it's a function in the wrong place, the addendum could be > generated: > > (Perhaps you meant to call the function, but left out a pair of parentheses.) > > The lack of line number information for errors in REPL evaluations is > also an issue. I suggest that when a defn is evaluated at the REPL, it > gets metadata like {:file REPL$user$fac :line 1} where the line number > counts from the "defn" on down. The message printer can parse the file > name from the exception and if it's REPL$anything parse it as > referring to a REPL evaluation and not an actual file, printing > something like "line 1 of user/fac" in the OP's instance. IDEs can > also possibly have go-to-error pull up the relevant line in the REPL > backbuffer, searching backwards for the most recent evaluation of > (defn fac ...) in user for instance and then finding line 1 of that. > When the error's in a normal source file, of course, existing behavior > is adequate for the most part (though there are sometimes problems > when macros are involved -- particularly, the line number is commonly > the start of the macro body, though not oddly when that macro is > "defn"). > > Clooj would be a good place to experiment with a friendlier REPL error > reporting system. > > -- > Protege: What is this seething mass of parentheses?! > Master: Your father's Lisp REPL. This is the language of a true > hacker. Not as clumsy or random as C++; a language for a more > civilized age. -- 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