Clojure ';如果';使用多个表达式抛出NullPointerException
我对Clojure ';如果';使用多个表达式抛出NullPointerException,clojure,Clojure,我对if的行为有点困惑。以下代码可以正常工作: (if true (let [x "whatever"] (println "TRUE 1") (println "TRUE 2"))) 返回: TRUE 1 TRUE 2 nil 但是如果删除了let表达式: (if true ( (println "TRUE 1") (println "TRUE 2"))) 它还返回一个NullPointerException: TRUE 1 TRUE 2 Nu
if
的行为有点困惑。以下代码可以正常工作:
(if true
(let [x "whatever"]
(println "TRUE 1")
(println "TRUE 2")))
返回:
TRUE 1
TRUE 2
nil
但是如果删除了let
表达式:
(if true
(
(println "TRUE 1")
(println "TRUE 2")))
它还返回一个NullPointerException
:
TRUE 1
TRUE 2
NullPointerException user/eval8051 (NO_SOURCE_FILE:4)
我怀疑这是由于
println
返回了nil
。但是,当引入let
时,它为什么会起作用呢?有更好的方法吗 关键部分是这个区块
((println "TRUE 1")
(println "TRUE 2"))
这样做的目的是计算println
s,将表达式转换为:
(nil nil)
然后,由于附加了括号,它尝试将nil
作为函数调用,并将nil
作为参数。由于nil
不是一个函数,因此它抛出异常。它在第一种情况下起作用的原因是它有let
来进行计算。由于let
将对其主体中的每个表达式求值(并且不会尝试将结果视为函数),因此它的行为是正确的
如果要计算多个表达式,应使用
或者,由于没有“其他”部分,您可以使用
需要记住的重要一点是,在Clojure中,与C风格语言不同,您不能在表达式周围添加括号而不更改其含义。如果你用括号括起来(不加引号),它将尝试将其作为函数调用进行计算。关键部分是这个块
((println "TRUE 1")
(println "TRUE 2"))
这样做的目的是计算println
s,将表达式转换为:
(nil nil)
然后,由于附加了括号,它尝试将nil
作为函数调用,并将nil
作为参数。由于nil
不是一个函数,因此它抛出异常。它在第一种情况下起作用的原因是它有let
来进行计算。由于let
将对其主体中的每个表达式求值(并且不会尝试将结果视为函数),因此它的行为是正确的
如果要计算多个表达式,应使用
或者,由于没有“其他”部分,您可以使用
需要记住的重要一点是,在Clojure中,与C风格语言不同,您不能在表达式周围添加括号而不更改其含义。如果您将某个内容括在括号中(不加引号),它将尝试将其作为函数调用进行计算。另请参阅:关于术语或发生的情况,有必要了解一些技术要点:第一个表达式不返回
“TRUE 1”
和“TRUE 2”
;它打印它们,并返回nil
。由于您在REPL中执行此操作,因此也会打印返回值:“nil”
。那么,您可能会认为,在第二个表达式中,只返回了NullPointerException
,但这并不完全正确。异常不是if
表达式的值;这是个例外。它中断了表达式的计算。因为它没有被捕获,所以它被打印出来了。另请参见:关于术语的一些技术要点,或者关于发生了什么,值得弄清楚:第一个表达式没有返回“TRUE 1”
和“TRUE 2”
;它打印它们,并返回nil
。由于您在REPL中执行此操作,因此也会打印返回值:“nil”
。那么,您可能会认为,在第二个表达式中,只返回了NullPointerException
,但这并不完全正确。异常不是if
表达式的值;这是个例外。它中断了表达式的计算。因为没有被抓到,所以被打印出来了。现在有意义了。谢谢你可爱的解释。现在说得通了。谢谢你可爱的解释。