Clojure'de tembel diziyi tembel olmayana dönüştürme


95

Clojure'da tembel olmayan bir dizinin sınıfının döndürülmesini bekleyerek aşağıdakileri denedim:

(.getClass (doall (take 3 (repeatedly rand))))

Ancak bu hala geri dönüyor clojure.lang.LazySeq. Tahminimce bu doall, tüm diziyi değerlendiriyor, ancak not alma için hala yararlı olduğu için orijinal diziyi döndürüyor.

Öyleyse, tembel olandan tembel olmayan bir sekans yaratmanın deyimsel yolu nedir?


Geri dönüş değerinin gerçek türü hakkında neden endişelendiğinizi kimsenin sormamasına şaşırdımdoall
tar

Bir vektöre dönüştürebilirsiniz:(vec (take 3 (repeatedly rand)))
Kris

Yanıtlar:


161

doalltüm ihtiyacın olan. Çünkü seqsahip tip LazySeqo değerlendirmeyi bekleyen anlamına gelmez. Tembeller seqsonuçlarını önbelleğe alır, bu nedenle tek yapmanız gereken, hepsini zorlamak için tembelliği bir seqkez (olduğu doallgibi) yürümek ve böylece tembel hale getirmek. seqyok değil tüm koleksiyonu zorlamak değerlendirilecek.


2
Bunu kabul edilen cevap olarak değiştirdim. İlgili bir notta, bir LazySeq'in daha önce değerlendirilip değerlendirilmediğini hangi yollarla belirleyebilirsiniz?
Tim Clemons

10
Sadece aradığına inanıyorum realized?.
toofarsideways

1
Muhtemelen realizeeşleşecek bir operasyon olmalı realized?.
Reut Sharabani

Bunların hepsi çok güzel. Ancak contains?, tembel sıralamayı fark edip etmediğinizi önemsemeyen gibi bazı işlevler , sorulduğu gibi belirli soruya yanıt verir, ancak sorunun başlığına daha az yanıt verir.
matanster

75

Bu bir dereceye kadar bir taksonomi sorunudur. tembel bir dizi, bir liste, vektör veya harita gibi yalnızca bir tür dizidir . Dolayısıyla cevap elbette "bu, ne tür tembel olmayan sekans elde etmek istediğinize bağlıdır:
Seçiminizi yapın:

  • eski tembel (tamamen değerlendirilmiş) tembel bir dizi (doall ... )
  • sıralı erişim listesi (apply list (my-lazy-seq)) OR (into () ...)
  • daha sonra rastgele erişim için bir vektör (vec (my-lazy-seq))
  • özel bir amacınız varsa bir harita veya set.

İhtiyaçlarınıza en uygun dizilim türüne sahip olabilirsiniz.


Bu en iyi cevap.
Felipe

4
Kabul edilen cevap teknik olarak doğrudur, ancak bu cevap benim için çok yararlı oldu. Bir vektör üzerinde bir işlevi eşleştirmeye ve sonuçları bir dosyaya aktarmaya çalışıyordum ve hatta doall çağrıldıktan sonra dosya, dizinin içeriği yerine "clojure.lang.LazySeq@address" içeriyordu. Döndürülen değer haritasındaki vec çağırmak, dosyaya tükürmek için ihtiyacım olan şeyi verdi.
Jesse Rosalia

1
@JesseRosalia Tüm SO'daki tek Rich Hickey cevabının teknik olarak doğru olduğunu bilmek güzel. ;-)
Phil Cooper

(vec (my-lazy-seq))aşağıdaki gibi durumlarda kadar güzel değil: (vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]]yana cheshireseçer dan tembel-seq üretmek için(json/parse-string)
codeasone

Yukarıdakiler için (json/parse-string-strict)
hafifletme,

22

Görünüşe göre bu Zengin adam, ne yapacağını biliyor ve kesinlikle haklı.
Ancak bence bu kod parçacığı, örneğinizi kullanarak, bu soru için yararlı bir tamamlayıcı olabilir:

=> (realized? (take 3 (repeatedly rand))) 
false
=> (realized? (doall (take 3 (repeatedly rand)))) 
true

Nitekim tipi değişmedi ancak gerçekleşme vardır


2
Yine de, tüm diziyi realized?geri dönmeye zorlamanıza gerek olmadığını belirtmekte fayda var true. Örneğin(let [r (range) r? (realized? r)] (doall (take 1 r)) [r? (realized? r)]) => [false true]
Alex Coventry

22
Bu Zengin adam: D haha
Julian Krispel-Samsel

10
@nimrod :) kelime oyunu ancak "onun clojure" içinde olması gerekiyordu.
Peter

10
Bilmeyenler için "Zengin adam" Clojure'u icat etti.
erturne

1
@AlexCoventry örneğiniz döndürür[true true]

7

Bu blog gönderisine doallyinelemeli olmama konusunda tökezledim . Bunun için gönderideki ilk yorumu buldum hile yaptı. Şu çizgide bir şey:

(use 'closure.walk)
(postwalk identity nested-lazy-thing)

Bunu, bazı iç içe yerleştirilmiş uygulamaların değerlendirmesini mapbir hata durumuna zorlamak için zorlamak istediğim bir birim testinde faydalı buldum .


5
(.getClass (into '() (take 3 (repeatedly rand))))

3
Bu berbat bir fikir. Giriş sırasını tersine çevirir.
amalloy

3
Elbette, bu durumda girdiyi tersine çevirmek fark etmez, çünkü bunlar sadece 3 rastgele sayıdır .... :-)
mikera
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.