2012-04-02 50 views
22

我想實現Clojure中的這個小的代碼,但我奮力:如何實現一個for循環的Clojure

struct mystruct { 
    int id; 
    int price; 
}; 

mystruct mydata[10]; 

for (int i=0; i<10; i++) { 
    myfunction(mydata[i].id, mydata[i].price); 
    //other things... 
} 

我使用Clojure一個初學者,它真的複雜,我做的事這樣簡單,但我真的很想學習,因爲我知道Clojure有很多優點,例如使用參考...

如果有人能幫助我,我將非常感激。謝謝!!

回答

32

一種將命令循環轉換爲Clojure的方法是使用for宏。

(for [i (range 10)] (inc i)) 

上述函數將返回從0到9加1,但是,似乎你只是想遍歷順序收集和利用每一個項目的所有號碼。如果這就是您需要的全部內容,那麼您不需要引用索引值,而是可以直接引用每個項目。

(for [d my-vec-of-data] (my-function d)) 

然而,對於這個簡單的情況下,map功能可能會是一個更好的選擇,因爲它的設計與館藏參數來調用功能。以下示例等同於使用上面的for

(map my-function my-vec-of-data) 

兩個mapfor返回由通過my-function返回值的值的集合。這是因爲Clojure的數據結構是不可變的,所以有必要返回一個新的集合。如果這不是你所需要的或者你的功能有副作用,你可以使用doseq而不是for,它返回nil

+2

是「我」自動遞增? – nuvio 2012-04-02 19:01:25

+1

@nuvio:'我'將成爲序列中的實際項目,而不是索引。是的,'for'宏將爲你處理迭代序列。 – Chuck 2012-04-02 19:04:50

+0

「doseq」非常適合不需要返回值的函數,因爲它返回單個零而不是每個元素 – jm0 2016-02-08 21:43:44

30

傑里米的回答對於如何在慣用Clojure中做一個for循環很有幫助。

如果你真的想要一個命令式的Clojure中的循環,你可以創建一個與此宏:

(defmacro for-loop [[sym init check change :as params] & steps] 
`(loop [~sym ~init value# nil] 
    (if ~check 
     (let [new-value# (do [email protected])] 
     (recur ~change new-value#)) 
     value#))) 

用法如下:

(for-loop [i 0 (< i 10) (inc i)] 
    (println i)) 
+29

我喜歡在Clojure中如何缺少語言功能,而不是等待它成爲添加到未來的版本中,你可以編寫自己的。 – Dale 2012-04-11 09:23:28