19

Why does the following Clojure program throw a NullPointerException?

user=> (defn x []  
       "Do two things if the expression is true."
       (if true ((println "first expr") (println "second expr")) false))

user=> (x)
first expr
java.lang.NullPointerException (NO_SOURCE_FILE:0)
second expr

This is a simplified version of my actual use case, where I want to execute maybe three statements (pull values from the DB) before returning a map - {:status 200, :body "Hello World"} inside of the branch.

1

3 Answers 3

36

It is trying to treat the result of the first println as a function to call on the second println function.

You need a do.

(defn x []  
   "Do two things if the expression is true."
   (if true (do (println "first expr") (println "second expr")) false))

(x)

The do special form (progn in CL, begin in Scheme) executes each of its arguments in sequence and returns the result of the last one.

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

3 Comments

Yes, generally. A few forms might imply it (Scheme cond implies it, for instance, but I don't think Clojure's version does since its arguments aren't in lists). ((foo ...) (bar ...)) generally implies taking the result of foo and using it as a function to call the rest of the arguments.
So does this mean that do will execute the statements sequentially? (it'll assume they have side effects)?
do will indeed execute its statements sequentially.
11

If nil is ok as a return value in the else case, consider using when which has an implicit do block:

(defn x []  
  "Do two things if the expression is true."
  (when true
    (println "first expr") 
    (println "second expr")))

Comments

7

Not that it matters in your particular case, but do know the difference between (do ...) which will load each form in its own classloader, and an empty let form (let [] ...) which evaluates the whole form in a single classloader.

2 Comments

What is the practical difference between loading each form in its own classloader vs otherwise? Maybe I don't understand the implications of classloader.
One example, you are writing a macro that defines a custom deftype and multiple classes. As an optimization, you would like to use the same classloader so that less classloader instances are created.

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.