Clojure 为什么(nil)的评估与((println";foo";)不同
为什么下面最后两行有差异?从REPL粘贴评估异常。我正在使用Clojure 1.4Clojure 为什么(nil)的评估与((println";foo";)不同,clojure,Clojure,为什么下面最后两行有差异?从REPL粘贴评估异常。我正在使用Clojure 1.4 (println "foo") ;; evals to nil (nil) ;; CompilerException java.lang.IllegalArgumentException: Can't call nil ((println "foo")) ;; NullPointerException 一个是编译时异常;另一个是运行时异常 在(nil)的情况下,编译器看到您正在尝试对nil进行函数调用,并给
(println "foo") ;; evals to nil
(nil) ;; CompilerException java.lang.IllegalArgumentException: Can't call nil
((println "foo")) ;; NullPointerException
一个是编译时异常;另一个是运行时异常 在
(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
没有编译器要检测的静态返回类型
但是编译器仍然可以检测只涉及值的类型错误