Clojure有短路逻辑吗?

时间:2011-11-18 23:28:33

标签: optimization clojure short-circuiting

在许多语言中,如果你按照

的方式写一些东西
if (foo() || bar() || foobar()) { /* do stuff */ }

和foo()返回true,然后不会评估bar()和foobar()。

假设我有以下Clojure代码:

(let [a (simple-function args)
      b (complex-function args)
      c (too-lazy-to-optimize-this-function args)]
  (or a b c))

如果评估为真,那么b和c也会被评估,还是会被忽略?

谢谢!

6 个答案:

答案 0 :(得分:12)

由于您回答了自己的问题,请注意虽然在您的示例中,b和c可能未在(或abc)调用中进行评估,但在此之前评估let绑定,因此太懒惰到优化此函数无论如何都要评估电话。 Clojure并不像那样懒惰。

要明确:要有条件地评估函数调用,您需要在or调用中将表达式进行评估,基本上:

(or (simple-function args)
    (complex-function args)
    (too-lazy-to-optimize-this-function args))

答案 1 :(得分:11)

其他答案都很好,但如果有疑问,你可以随时在REPL上测试它:

user=> (or true (do (println "hello") true))
true
user=> (or false (do (println "hello") true))
hello
true

答案 2 :(得分:4)

如有疑问,请咨询the documentation

  


  宏
  用法:

   (or)  
   (or x)  
   (or x & next)  
     

从左到右逐个评估exprs。如果是表格   返回逻辑真值,或返回该值而不是   评估任何其他表达式,否则返回   最后一个表达式的值。 (或)返回nil。

(强调我的。)

documentation for and表明它的行为也相同。

答案 3 :(得分:1)

一旦我完成了这个问题的输入,我就意识到我可以查看'或'的文档。

来自文档:  “从左到右一次评估exprs。如果是表格   返回逻辑真值,或返回该值而不返回   评估任何其他表达式,否则返回   最后一个表达式的值。 (或)返回nil。“

答案 4 :(得分:1)

是的,Clojure确实有短路评估。

Clojure /其他Lisps中的一个有趣特性是,也可以使用也提供短路评估的新结构扩展语言。这不能使用大多数其他语言中的函数来完成,因为在调用函数之前必须评估函数的所有参数。

以下是在Clojure中实现短路NAND功能的宏示例:

(defmacro nand 
  ([x] 
    `(not ~x))              ; NAND is equivalent to NOT for one argument
  ([x & xs] 
    `(let [nand# (not ~x)]
       (if nand# 
         true               ; short circuit if we can prove the nand is true
         (nand ~@xs)))))    ; continue with the other expressions otherwise

(nand true true)
=> false

(nand false (println "Expression with a side effect!"))
=> true

答案 5 :(得分:0)

if (foo() || bar() || foobar()) { /* do stuff */ }

(if (or (foo) (bar) (boobar)) (comment do stuff))

(when (or (foo) (bar) (boobar)) (comment do stuff))