This week's giveaway is in the Android forum.
We're giving away four copies of Android Security Essentials Live Lessons and have Godfrey Nolan on-line!
See this thread for details.
The moose likes Clojure and the fly likes Getting more information from an error Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Languages » Clojure
Bookmark "Getting more information from an error" Watch "Getting more information from an error" New topic
Author

Getting more information from an error

Christophe Verré
Sheriff

Joined: Nov 24, 2005
Posts: 14687
    
  16

I'm trying the Euler problems as suggested by one of the author of this week's promotion. I'm obviously lacking any solid ground in Clojure, so I'm struggling to get any results.

After I imported my script from REPL, I get an error at execution : java.lang.ClassCastException: java.lang.Boolean. Great. But that doesn't tell me where, and I can understand where the problem is just by looking at the code. Is there a way to get more information from an error like this ?


[My Blog]
All roads lead to JavaRanch
Christophe Verré
Sheriff

Joined: Nov 24, 2005
Posts: 14687
    
  16

I figured out that some extra parents were causing the error:

instead of

How do you troubleshoot that ?
Chris Houser
author
Greenhorn

Joined: Feb 07, 2011
Posts: 22

Congrats on writing and running some real Clojure code of your own!

In the latest Clojure 1.3 pre-release snapshot, my error looks like this:

The name of the file (tmp.clj) and line number (6) causing the error are right there. From the message itself I can see I was trying to use a boolean value (true or false) as if it were an IFn, which is short for Function Interface. This almost always means there's an expression at the beginning of a set of parens that isn't actually a function. And of course that's the problem here -- the result of (zero? ...) is a boolean, and since that was wrapped in another set of parens, Clojure was trying to call the boolean, as if it were a function.

If that's not sufficient detail, you can use (pst) afterwards at the REPL and you'll see something like this:

This doesn't help much in our case, but what it's showing here is the full stack trace, from the function that cause the error at the top, all the way back to [tt]eval[\tt] function in the repl that started it all. Note that I'm running a slightly customized repl, so my stack trace may look a bit different from yours. Anyway, this kind of full stack trace is frequently useful in larger programs.

If you're using Clojure 1.2, things aren't quite so pretty:

Here it's pointing to a file and line number that is not helpful, so looking at the full stack trace may be worth while. To do that in Clojure 1.2, you must write (.printStackTrace *e), which presents you with this loveliness:

That's pretty daunting, but don't panic -- the details you want are in there. As we describe in the book, start with the root cause near the bottom of that listing, the last place it says "Caused by". Now, look at the following line and there's the information pointing you to exactly which line of your file was causing the problem -- tmp.clj line 6.

You can see some improvements have been made in this arena in recent versions of Clojure.
Christophe Verré
Sheriff

Joined: Nov 24, 2005
Posts: 14687
    
  16

Congrats on writing and running some real Clojure code of your own!

The learning curve is going to be steep. I'm fighting with (doc ...) in one hand and Google in another (doc ...) is almost useless, or don't know yet how to get something concrete out of it. Quite a change from the well documented Java API.

the result of (zero? ...) is a boolean, and since that was wrapped in another set of parens, Clojure was trying to call the boolean, as if it were a function.

Crystal clear explanation. Thanks.

I'm using Clojure 1.2 and, as you said, (.printStackTrace *e) did give me more information. Thanks again !

As you said, the important part is : user$euler$fn__4.invoke(euler1.clj:4). Now I know which line the error is !
I wonder why I have "NO_SOURCE_FILE:0". Is it because I'm loading my script via (load "euler1") ?
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Getting more information from an error
 
Similar Threads
Getting error "Oops! This link appears to be broken."
TESTS STATISTICS
Sorting NestedLoops
some value too large for some column and getting a SQL trace from Oracle, a 30 year old database
org.apache.axis2.description.ClientUtils inferOutTransport