2010-07-15 18 views
6

Bunun gibi bir kod var. Bunu replde çalıştırabilirim ama komut satırından yapamam. Sanırım tembel bir değerlendirme problemim var.Tembel değerlendirme problemi


; items.clj 

(def items (ref [])) 

(defn init-items [] 
    (map 
    #(dosync 
     (alter items conj %)) 
    ["foo" "bar" "baz" ])) 

(init-items) 
(println (first @items)) 

$ java -jar clojure.jar items.clj 
$ nil 

Selamlar.

cevap

4

Anladım! Hiçbir sonuç döndürdü olmadığından

solution

Clojure init-items yılında map fonksiyonunu çalıştırmak için motive değildir. Uygulamayı zorlamak ve presto için doall içine sardım.

+0

Ben çalıştı. Çok teşekkürler. – Osman

+3

Aslında 'dorun' bu dava için daha uygundur ('doall' sarar ve onu döndürür, sonra 'dorun' adım adım atar ve sonunda nil 'döndürür - bu yüzden daha uygun yan etki kodu). –

+0

@Michal: Elbette kesinlikle haklısınız. Clojure'la biraz konuştum ama asla yüksek yetkinliğe ulaşmadım ve şimdi, ne yazık ki, paslanmaya bile başlıyor. Düzeltme için teşekkürler! –

4

Bazı alternatifler:

sadece öğe başına bir işlemin başlatılması, bir Ref düzenlenen bir koleksiyona öğelerin bir demet eklemek istiyorsanız ve conj bunları ayrı ayrı ing biraz savurgan olduğunu. Bunun yerine, tek maddelik başına adım moda yapmak için bir nedeniniz yoksa

(defn init-items [] 
    (dosync (alter items into ["foo" "bar" "baz"]))) 

yapabileceği, ben en deyimsel ve uygun bir yöntem şu anda kullanmak olacağını düşünüyorum doseq:

(defn init-items [] 
    (doseq [item ["foo" "bar" "baz"]] 
    (dosync (alter items conj item)))) 

(Ya da bir dosync sarın tüm doseq taşımak ve doseq 'ın vücudunda dosync kullanamadı.)