2011-11-18 76 views
5

在许多语言中,如果你写沿Clojure有短路逻辑吗?

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

和Foo(东西线)返回true,则巴()和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也进行评估,还是会被忽略?

谢谢!

回答

12

既然你回答了你自己的问题,要注意的是,虽然在你的榜样b和c可能不会在(或ABC)调用评估,在此之前评估let绑定,因此无论如何都要评估过于懒惰的优化此函数调用。 Clojure并不像那样懒惰。

需要明确的是:根据条件计算函数调用,你需要把该表达的or通话评价他们,基本上是:

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

我接受这一个,因为它讨论疑难杂症,我是不知道的。 – Joel

+4

这不是一个难题,而是你必须了解除懒惰序列以外的所有事情,以及对它们有效的功能。因为它是一个宏,所以'或'短路,它扩展到http://bit.ly/u8xnms。如果它是一个函数,它会评估它的论点。相反,它会扩大到一个if,这是一种特殊的形式和短路。 – gtrak

1

只要我输完这个问题,我意识到我可以看看'或'的文档。

从文档: “的计算结果exprs一次一个,从左至右如果窗体 返回逻辑真值,或返回值,不 评估其他任何表情,否则。返回最后一个表达式的 值。(或)返回nil。“

4

如有疑问,请咨询the documentation


宏观
用法:

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

在时评估exprs之一,由左到右。如果表格 返回逻辑真值,或者返回该值而不是 评估任何其他表达式,否则返回 值。 (或)返回零。

(重点煤矿。)

documentation for and显示它在等效的方式表现了。

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

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

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

其他的答案都好,但如果有疑问,可以总是只对REPL进行测试:

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

+1用于演示而不是陈述! – mikera

1

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

Clojure /其他Lisp的一个有趣特征是它也可以用新的构造来扩展语言,这些构造还提供了短路评估。这不能用大多数其他语言中的函数来完成,因为函数的所有参数都必须在调用该函数之前进行评估。

这里有一个宏观的例子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 [email protected]))))) ; continue with the other expressions otherwise 

(nand true true) 
=> false 

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