2014-06-11 39 views
2

我使用Clojure很新。我有一個包含一個布爾變量的Java方法,我想重寫這個方法在Clojure中也使用它。但是我無法找到如何在Clojure中的運行時設置布爾值true和false。轉換了Java概念引入Clojure的

下面的代碼片段基本上只強調布爾的一部分,這是很難想象對我來說,一個功能性的方式寫這篇文章。

int calculate(...){ 
    int y = 0; 
    boolean flag = false; 
    foreach(...){ 
    if(!flag){ 
     y = 1; 
     flag = true; 
    } 
    else{ 
     y = -1; 
     flag = false; 
    } 
    } 
    return y; 
} 

下面是我在Clojure的第一次嘗試:

(defn calculate [...] 
    (??flag?? -> I do not know which macro I should use over here 
     (doseq [x ...] 
     (if (false? flag) (do 1 (set the flag true)) 
      (do -1 (set the flag false))))) 

我如何能實現Clojure中的同一個概念?

+0

從概念上講,使用輔助函數和遞歸函數可能會更清潔 - '(defn calculate [y flag] ..)' – user2864740

+0

這個程序沒有任何意義......你循環收集元素,翻轉y的值 - 是「標誌」意味着代表集合中每個元素的某些功能?如果不是,只需返回1或-1,具體取決於集合是否具有奇數或偶數個元素 – Hendekagon

+3

您問「*我怎樣才能在Clojure中實現相同的概念?」。 *爲什麼*你想這樣做?即使在可能的情況下Java的點語翻譯成Clojure通常也是徒勞的。直到你的Java程序有意義,很難看到如何在慣用的Clojure中渲染它的功能。如果你想在Clojure中解決明確的小問題,請看看[4Clojure](http://www.4clojure.com/)。如果您想將Clojure解決方案與Java和其他語言的解決方案進行比較,[Rosetta Code](http://rosettacode.org/wiki/Rosetta_Code)是一個很好的來源。我發現這兩個都非常有幫助。祝一切順利! – Thumbnail

回答

7

對於你的Java代碼,它看起來像最簡單的方法把它翻譯成的Clojure將跳過所有迭代,就回到終值:

(defn calculate [coll] 
    (odd? (count coll))) 

如果你想要的東西更復雜的我想你可以做這樣的事情

(defn calc [coll flag] 
    (if (empty? coll) 
    flag 
    (recur (rest coll) (not flag)))) 

,並把它

(defn calculate [coll] 
    (calc coll false))  

這種遞歸是不是最慣用的風格,這是一種瘋狂的這個問題,但它演示瞭如何進行變異的變量,而不是寫評價時,其產生傳遞到下一個迭代值的表達式(見易復發通話在上面的例子中)。

這將是更好的風格改寫這個像

(defn calculate 
    ([coll flag] 
    (if (empty? coll) 
     flag 
     (recur (rest coll) (not flag)))) 
    ([coll] 
    (calculate coll false))) 

所以,只有一個函數名來處理。 (我以另一種方式認爲它可能會更清晰地閱讀Clojure的新手。)

我第二條評論建議你看看4clojure。這是獲得練習的好方法,一旦你有了解決方案,你可以從其他用戶那裏學習。

2

使用loop/recur效仿迭代語句用Clojure:

(defn calculate [...] 
    (loop [... 
     y 0 
     flag false] 
    ... 
    (if (false? flag) 
     (recur ... 1 true) ;; "loop with x = ..., y = 1 and flag = true" 
     (recur ... -1 false)) ;; "loop with x = ..., y = -1 and flag = false" 
    ...) 

編輯:讓我細說。我從你的問題中瞭解到,你無法將基於可變性(Java)的代碼翻譯成Clojure。這很自然。 Clojure在不變性方面很重要。

在Clojure程序中實現可變性的一種方法是使用引用類型,特別是​​。你的一段代碼可以這樣寫在Clojure:

(defn calculate [...] 
    (let [y (atom 0) 
     flag (atom false)] 
    (doseq [x ...] 
     (if (false? @flag) 
     (do (reset! y 1) 
      (reset! flag true)) 
     (do (reset! y -1) 
      (reset! flag false)))) 
    (... return some function of y and flag ...))) 

它的工作原理。但是在Clojure中大量使用原子和副作用並不是慣用的;與功能性,慣用的Clojure相比,是的,但並非必要且麻煩。

在迭代的上下文中模擬可變性的更好方法是按照遞歸方式來轉換它,就像我上面做的loop/recur