2012-04-02 34 views
22

yılında döngü için bir uygulamaya nasıl Clojure bu küçük kod uygulamak istiyorum ama mücadele ediyorum: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... 
} 

Ben Clojure ile bir acemi ve bana bir şeyler yapmak için gerçekten karışık Bu gibi basit, ama ben gerçekten birileri bana yardımcı olabilir eğer ben gerçekten takdir edersiniz. Teşekkürler!!

cevap

32

Döngü için bir emrin tamamını Clojure'a çevirmenin bir yolu, for makrosunu kullanmaktır.

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

yukarıdaki fonksiyon Ancak, sadece sıralı topluluğu üzerinde yineleme ve her bir öğeyi kullanmak istediğiniz görünür 1 artırılır 0'dan 9'a kadar bütün rakamları dönecektir. İhtiyacınız olan tek şey buysa, o zaman bir endeks değerine başvurmanıza gerek yoktur, bunun yerine doğrudan her bir öğeye başvurabilirsiniz. o koleksiyonlardan argümanlarla işlevleri çağırmak için tasarlandığından,

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

Ancak bu basit bir durum için, map fonksiyon muhtemelen daha iyi bir seçim olacaktır. Aşağıdaki örnek, yukarıdaki for kullanımına eşdeğerdir.

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

Hem map ve my-function tarafından döndürülen değerlerin oluşturduğu bir değerler topluluğu dönmek for. Bunun nedeni Clojure'un veri yapılarının değişmez olmasıdır, bu yüzden yeni bir koleksiyonun iade edilmesi gerekmektedir. İhtiyacınız olan şey bu değilse veya işlevinizin yan etkileri varsa, nil değerini döndüren for yerine doseq kullanabilirsiniz.

+2

'i' otomatik artırmaz gelmez

gerçekten Clojure içinde döngü için bir zorunluluk tarzı istiyorsanız

, bu makro ile bir tane oluşturabilirsiniz? – nuvio

+1

@nuvio: 'Dizinde değil, dizideki asıl öğe olacak. Ve evet, 'for' makrosu sizin için sıralamayı yineleyecek. – Chuck

+0

"doseq" bir dönüş değerine gerek duymadığınız fonksiyonlar için mükemmeldir, çünkü eleman başına 1 nolu yerine tek bir sıfır döndürür – jm0

30

Jeremy'nin cevabı deyimsel Clojure'da bir for döngüsünün nasıl yapılacağı konusunda iyidir. aşağıdaki gibi

(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#))) 

Kullanımı:

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

Eğer eksik bir dil özelliğiniz varsa Clojure uygulamasının nasıl olmasını beklemek yerine Gelecek bir sürüme eklendi, sadece kendi yazabilirsiniz. – Dale