2011-02-09 48 views
24

我在教自己Clojure。if-else在clojure中分支

在非FP語言中,我可以很容易地編寫嵌套if語句,並且如果我沒有專門輸入else語句,那麼控制流就會流出if語句塊。例如:

Thing myfunc() 
{ 
    if(cond1) 
    { 
    if(cond2) 
     return something; 
    } 
    return somethingelse; 
} 

然而,在Clojure中,沒有return語句(據我所知),所以如果我寫:

(defn myfunc [] 
    (if (cond1) 
     (if (cond2) something)) 
    somethingelse) 

那麼就沒有的 「東西」, 「回報」。這似乎只是說,好吧,在這裏我們有一個價值,現在讓我們繼續執行。顯而易見的解決辦法是組合條件,例如:

(if (and (cond1) (cond2)) 
    something 
    somethingelse) 

但是這對於大的條件來說很笨拙/醜陋。此外,還需要額外的努力才能將語句添加到cond1的「其他」部分。有沒有什麼優雅的解決方案呢?

+0

我不明白它是如何得到「笨重」。你能舉一些例子嗎? – Svante 2011-02-09 11:00:24

+0

我正在處理的問題涉及檢查兩個數字是否都是3位數字。它看起來非常難看(如果(和(= 3(count(str num1)))(= 3(count(str num2))))) – Kricket 2011-02-09 12:54:57

+1

聽起來像你需要一個函數! `(defn three?[num](= 3(count(str num))))`然後你需要的是`(if(and(three?num1)(three?num2))something) – Jeremy 2011-02-09 12:58:51

回答

30

這是命令式和功能式方法之間的細微區別。必要時,您可以將return放置在函數的任何位置,而功能性最好的方法是具有清晰明確的執行路徑。有些人(包括我)在命令式編程中更喜歡後一種方法,認爲它更明顯,易於管理,並且不易出錯。

爲了使這個功能明確:

Thing myfunc() { 
    if(cond1) { 
    if(cond2) 
     return something; 
    } 

    return somethingelse; 
} 

你可以將它重構爲:

Thing myfunc() { 
    if(cond1 && cond2) { 
     return something; 
    } else { 
    return somethingelse; 
    } 
} 

在Clojure中,其等效爲:

(defn myfunc [] 
    (if (and cond1 cond2) 
     something 
     somethingelse)) 

如果你需要一個「別人「,您的Java版本可能會變爲:

Thing myfunc() { 
    if(cond1) { 
    if(cond2) { 
     return something; 
    } else { 
     return newelse; 
    } 
    } else { 
    return somethingelse; 
    } 
} 

...和它等價的Clojure:

(defn myfunc [] 
    (if cond1 
     (if cond2 something newelse) 
     somethingelse)) 
15
(if (and (cond1) (cond2)) 
    something 
    somethingelse) 

(cond 
    (and (cond1) (cond2)) something 
    :else somethingelse) 

cond做,如果你想比較同樣的事情做;在開關盒中,您可以使用condp

我沒有經常看到這種類型的代碼,但這是做到這一點的方法。

7

有Clojure中沒有明確return語句,但你的代碼的「東西」,將「迴歸」,因爲你沒有那個if後和Clojure中的最後一個表達式的結果的任何表達式作爲函數的返回值

14

命令式語言有if語句,說if this then do that else do that和功能語言有if-expressions,說if this return that else return this。這是一種看待同樣想法的不同方式,它反映了表達問題的非常不同的方法。在函數式語言中,所有值都是,即使您沒有對該值做任何事情,也是如此。

當我正在進行轉換時,它很大程度上幫助我自我「這個函數返回什麼結果」,而不是「我該習慣於問什麼」這個函數應該做什麼「的問題。

0

您也可以使用(cond)宏:

(defn length-checker [a b] 
    (cond 
    (= 3 (count (str a))) (if (= 3 (count (str b))) 
        (println "both numbers are 3 digits long") 
        (println "first number is 3 digits, but the 2nd not!")) 
    :else (println "first- or both of the numbers are not 3 digits")))