Wypróbowałem następujące czynności w Clojure, spodziewając się, że zwrócona zostanie klasa nieleniwej sekwencji:
(.getClass (doall (take 3 (repeatedly rand))))
Jednak to wciąż powraca clojure.lang.LazySeq
. Domyślam się, że doall
ocenia całą sekwencję, ale zwraca oryginalną sekwencję, ponieważ jest nadal przydatna do zapamiętania.
Więc jaki jest idiomatyczny sposób tworzenia nieleniwej sekwencji z leniwej?
clojure
lazy-evaluation
Tim Clemons
źródło
źródło
doall
(vec (take 3 (repeatedly rand)))
Odpowiedzi:
doall
to wszystko czego potrzebujesz. Tylko dlatego, żeseq
typ hasLazySeq
nie oznacza, że oczekuje na ocenę. Leniwy zapisuje wseq
pamięci swoje wyniki, więc wszystko, co musisz zrobić, to przejśćseq
raz leniwego (takdoall
samo jak ), aby wymusić to wszystko, a tym samym uczynić go nie leniwym.seq
nie nie zmusi całą kolekcję do oceny.źródło
realized?
.realize
operacjarealized?
.contains?
nie dbają o to, czy zdałeś sobie sprawę z leniwej sekwencji, czy nie, to odpowiada na konkretne pytanie, które zostało zadane, ale mniej na tytuł pytania.Do pewnego stopnia jest to kwestia taksonomii. leniwa sekwencja to tylko jeden typ sekwencji, podobnie jak lista, wektor czy mapa. Odpowiedź brzmi więc oczywiście „to zależy od tego, jakiego typu nie leniwą sekwencję chcesz uzyskać:
Wybierz spośród:
(doall ... )
(apply list (my-lazy-seq)) OR (into () ...)
(vec (my-lazy-seq))
Możesz mieć dowolny typ sekwencji, który najbardziej odpowiada Twoim potrzebom.
źródło
(vec (my-lazy-seq))
nie jest takie przyjemne w sytuacjach takich jak poniżej:(vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]]
Ponieważcheshire
decyduje się na produkcję lazy-seq z(json/parse-string)
(json/parse-string-strict)
Wydaje się, że ten bogaty facet zna swój strój i ma całkowitą rację.
Ale myślę, że ten fragment kodu, używając twojego przykładu, może być przydatnym uzupełnieniem tego pytania:
=> (realized? (take 3 (repeatedly rand))) false => (realized? (doall (take 3 (repeatedly rand)))) true
Rzeczywiście typ się nie zmienił, ale realizacja zmieniła się
źródło
realized?
do powrotutrue
. Np.(let [r (range) r? (realized? r)] (doall (take 1 r)) [r? (realized? r)]) => [false true]
[true true]
Natknąłem się na tym wpisie na blogu o
doall
tym, że nie jest rekurencyjny. W tym celu stwierdziłem, że pierwszy komentarz w poście załatwił sprawę. Coś w rodzaju:(use 'closure.walk) (postwalk identity nested-lazy-thing)
Znalazłem to przydatne w teście jednostkowym, w którym chciałem wymusić ocenę niektórych zagnieżdżonych aplikacji,
map
aby wymusić stan błędu.źródło
(.getClass (into '() (take 3 (repeatedly rand))))
źródło