Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27286

why does (nil) evaluate differently than ((println "foo"))

Why the discrepancy in the last two lines below? Evaluation exceptions are pasted from the REPL. I am using Clojure 1.4

(println "foo") ;; evals to nil

(nil)  ;; CompilerException java.lang.IllegalArgumentException: Can't call nil
((println "foo")) ;; NullPointerException

Upvotes: 2

Views: 263

Answers (1)

A. Webb
A. Webb

Reputation: 26446

One is a compile time exception; the other is a run-time exception.

In the case of (nil) the compiler sees your are trying to make a function call to nil and gives you a compile error.

In the case of ((println "foo")) the compiler does not try to infer what the inner form (println "foo") will return. For all it knows it could return a function, so the check does not occur at compile time. The exception occurs at run-time when indeed println returns a nil and you attempt to call it.

Being a dynamic language means you don't generally try to detect type errors of variables at compile-time.

Observe:

(.setDynamic #'println)

(binding [println 
           (fn [x] 
             (when (pos? (rand-int 2)) 
               (fn [] (print "bar\n"))))] 
  ((println "foo")))

which will randomly either print "bar" and return nil with no run-time exception or print nothing and throw a run-time NullPointerException. Here it is clear this contrived println has no static return type for the compiler to detect.

But the compiler can still detect type errors involving only values.

Upvotes: 8

Related Questions