2011-11-18 78 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