Reputation: 27286
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
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