为什么下面最后两行的差异?评估异常从REPL粘贴。我正在使用Clojure 1.4
(println "foo") ;; evals to nil
(nil) ;; CompilerException java.lang.IllegalArgumentException: Can't call nil
((println "foo")) ;; NullPointerException
答案 0 :(得分:8)
一个是编译时异常;另一个是运行时异常。
在(nil)
的情况下,编译器看到您正在尝试对nil
进行函数调用,并给出编译错误。
在((println "foo"))
的情况下,编译器不会尝试推断内部形式(println "foo")
将返回的内容。总而言之,它知道它可以返回一个函数,因此在编译时不会进行检查。当println
确实返回nil
并且您尝试调用它时,会在运行时发生异常。
作为动态语言意味着您通常不会尝试在编译时检测变量的类型错误。
观察:
(.setDynamic #'println)
(binding [println
(fn [x]
(when (pos? (rand-int 2))
(fn [] (print "bar\n"))))]
((println "foo")))
将随机打印“bar”并返回nil
,没有运行时异常或者不打印任何内容并抛出运行时NullPointerException
。这里很明显这个设计的println
没有静态返回类型供编译器检测。
但编译器仍然可以检测仅涉及值的类型错误。