以下の最後の2行に不一致があるのはなぜですか?評価例外はREPLから貼り付けられます。Clojure1.4を使用しています
(println "foo") ;; evals to nil
(nil) ;; CompilerException java.lang.IllegalArgumentException: Can't call nil
((println "foo")) ;; NullPointerException
以下の最後の2行に不一致があるのはなぜですか?評価例外はREPLから貼り付けられます。Clojure1.4を使用しています
(println "foo") ;; evals to nil
(nil) ;; CompilerException java.lang.IllegalArgumentException: Can't call nil
((println "foo")) ;; NullPointerException
1つはコンパイル時の例外です。もう1つは、実行時の例外です。
コンパイラの場合、(nil)
あなたが関数呼び出しを行おうとしていることを確認しnil
、コンパイルエラーを出します。
コンパイラの場合((println "foo"))
、内部フォームが何を返すかを推測しようとはしません(println "foo")
。関数を返す可能性があることはわかっているので、コンパイル時にチェックは行われません。例外は、実行時に実際にaをprintln
返し、nil
それを呼び出そうとしたときに発生します。
動的言語であるということは、通常、コンパイル時に変数の型エラーを検出しようとしないことを意味します。
観察:
(.setDynamic #'println)
(binding [println
(fn [x]
(when (pos? (rand-int 2))
(fn [] (print "bar\n"))))]
((println "foo")))
これは、ランダムに「バー」をnil
出力して実行時例外なしで戻るか、何も出力せずに実行時をスローしますNullPointerException
。ここで、この考案されprintln
たものには、コンパイラが検出する静的な戻り型がないことは明らかです。
ただし、コンパイラは、値のみを含むタイプエラーを検出できます。