2009-10-29 12 views
83

Próbowałem następujących w Clojure, oczekując mieć klasę non-lazy sekwencji wrócił:Jak przekonwertować do leniwe sekwencję non-leniwy w Clojure

(.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ętywania.

Co to jest idiomatyczny sposób tworzenia niepłynnej sekwencji z leniwego?

+0

Jestem zaskoczony, nikt nie zapytał, dlaczego jesteś zaniepokojony faktycznym typem zwracanej wartości 'doall' – tar

+0

Możesz przekonwertować na wektor:' (vec (wziąć 3 (wielokrotnie rand))) – Kris

Odpowiedz

139

doall to wszystko czego potrzebujesz. Tylko dlatego, że seq ma typ LazySeq, nie oznacza, że ​​oczekuje na ocenę. Lazy seqs cache ich wyniki, więc wszystko, co musisz zrobić, to chodzić leniwy seq raz (jak to robi), aby wymusić wszystko, a tym samym uczynić go non-leniwy. seq ma wartość , a nie wymusza ocenę całej kolekcji.

+2

I ' ve zmienił to na zaakceptowaną odpowiedź. W powiązanej notatce, w jaki sposób możesz ustalić, czy LazySeq został wcześniej oceniony? –

+10

Wierzę, że nazywasz po prostu "zrealizowany?". – toofarsideways

+1

Prawdopodobnie powinna istnieć operacja 'realizuj ', aby dopasować' zrealizowany? '. –

4
(.getClass (into '() (take 3 (repeatedly rand)))) 
+3

To jest okropny pomysł. Odwraca wejście seq. – amalloy

+3

Oczywiście w tym przypadku cofnięcie wejścia nie ma znaczenia, ponieważ są to tylko 3 przypadkowe liczby ... :-) – mikera

57

Jest to w pewnym stopniu kwestia taksonomii. Leniwa sekwencja to tylko jeden typ sekwencji jak lista, wektor lub mapa. Więc odpowiedź brzmi oczywiście „to zależy od tego, jakiego typu non leniwe sekwencji chcesz uzyskać:
Wybieraj spośród:

  • An (w pełni ocenione) leniwy sekwencja ex-leniwy (doall ...)
  • listy dla dostępu sekwencyjnego (apply list (my-lazy-seq)) OR (into() ...)
  • wektorem losowym dostępie do późniejszego (vec (my-lazy-seq))
  • mapę lub zestaw jeśli masz jakiś szczególny cel.

Możesz mieć dowolną sekwencję większości apartamentów do swoich potrzeb.

+0

To jest najlepsza odpowiedź. –

+3

Przyjęta odpowiedź jest poprawna technicznie, ale ta odpowiedź była dla mnie najbardziej przydatna. Próbowałem odwzorować funkcję na wektor, a następnie wypluć wyniki do pliku, a nawet po wywołaniu doall, plik zawierał "[email protected]" zamiast zawartości sekwencji. Wywołanie vec na zwróconej mapie wartości dało mi to, czego potrzebowałem, aby wypluć do pliku. –

+1

@JesseRosalia Dobrze wiedzieć, że jedyna jedyna odpowiedź Richa Hickey'a w całym SO była technicznie poprawna. ;-) –

18

Ten bogaty facet zdaje się znać swój clojure i ma absolutną rację.
Buth myślę, że ten kod-fragment, używając przykładu, może być użytecznym uzupełnieniem tego pytania:

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

Rzeczywiście typu nie zmieniło, ale realizacji został

+2

Warto jednak zauważyć, że nie trzeba wymuszać całej sekwencji dla' zrealizowanych? ', aby zwrócić 'true'. Na przykład. '(niech [r (zakres) r? (zrealizowane? r)] (doall (weź 1 r)) [r? (zrealizowane? r)]) => [false true]' –

+15

Ten bogaty facet: D haha ​​ – nimrod

+7

@ nimrod :) jednak gra miała być w "hís clojure". – Peter

6

Natknąłem się na ten temat ten blog post o około doall nie jest rekursywny. W tym znalazłem pierwszy komentarz w poście załatwił sprawę. Coś wzdłuż linii:

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

Znalazłem to użyteczne w badanej jednostki, gdzie chciałem wymusić ocenę niektórych zagnieżdżonych zastosowań map wymusić stan błędu.

Powiązane problemy