5

In the following code, Clojure (1.2) is printing the wrong message:

(try
  (let [value "1,a"]
    (map #(Integer/parseInt %) (.split value ",")))
  (catch NumberFormatException _ (println "illegal argument")))

This should print "illegal argument", but instead it prints a (1#<NumberFormatException java.lang.NumberFormatException: For input string: "a">.

What am I doing wrong?

Is this because of the lazy sequence returned by map? How should it be written?

1

1 Answer 1

10

The try special form only catches exceptions that are raised during during the dynamic extent of the body code. Here map is returning a lazy sequence, which then is passed out of the try special form and returned. The printer then evaluates the sequence, and at that point the exception is thrown.

Wrapping the map in doall should fix your problem.

Sign up to request clarification or add additional context in comments.

5 Comments

I actually tried that. It still seems to return a NFE wrapped in a RuntimeException.
@Ralph: Under 1.3 it works. You could wrap the parseInt call with try and return some sensible value if an exception occurs. If that is not appropriate, you could return nil when an exception occurs, and check to see if the resulting sequence contains nil to determine if an exception occurred and then act appropriately.
The second suggestion (return nil) sounds reasonable. I'll check that out.
I tried the nil substitution solution and it worked like a charm. Thanks!
This example skips invalid solutions using the above nil substitution method: (let [value "1,a"] (remove nil? (map #(try (Integer/parseInt %) (catch Exception _ nil)) (.split value ","))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.