2012-04-02 9 views
22

のループのために実装する方法を、私はClojureの中にこの小さなコードを実装したいのですが、私は苦労しています: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

命令のforループをClojureに変換する1つの方法は、forマクロを使用することです。

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

上記の機能はしかし、あなたが単にシーケンシャルコレクションを反復処理し、各アイテムを使いたい見える1インクリメント0から9までのすべての数字を返します。必要なものだけあれば、インデックス値を参照する必要はなく、各アイテムを直接参照することができます。コレクションからの引数を持つ関数を呼び出すように設計されているので

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

しかし、この単純な場合のために、map機能は、おそらくより良い選択でしょう。次の例は、上記のforの使用に相当します。

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

両方mapformy-functionによって返された値で構成された値のコレクションを返します。これは、Clojureのデータ構造が不変なので、新しいコレクションを返す必要があるためです。それがあなたが必要としているものでない場合、または機能に副作用がある場合は、forの代わりにdoseqを使用して、nilを返すことができます。

+2

は、「i」は自動的にインクリメントしますか? – nuvio

+1

@nuvio: 'i'は、インデックスではなく、シーケンス内の実際のアイテムになります。もちろん、 'for'マクロはあなたのためにシーケンスを繰り返し処理します。 – Chuck

+0

"doseq"は、要素あたり1個ではなく1個のnilを返すので、返値を必要としない関数には最適です。 – jm0

30

Jeremyの答えは、慣用的な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