Tentei o seguinte em Clojure, esperando o retorno da classe de uma sequência não preguiçosa:
(.getClass (doall (take 3 (repeatedly rand))))
No entanto, isso ainda retorna clojure.lang.LazySeq
. Meu palpite é que doall
avalia a sequência inteira, mas retorna a sequência original, pois ainda é útil para memoização.
Então, qual é o meio idiomático de criar uma sequência não preguiçosa a partir de uma sequência preguiçosa?
clojure
lazy-evaluation
Tim Clemons
fonte
fonte
doall
(vec (take 3 (repeatedly rand)))
Respostas:
doall
é tudo o que você precisa. Só porqueseq
tem tipoLazySeq
não significa que tenha avaliação pendente. Os preguiçososseq
armazenam seus resultados em cache, portanto, tudo o que você precisa fazer é acompanhar o preguiçososeq
uma vez (comodoall
faz) para forçar tudo e, assim, torná-lo não preguiçoso.seq
se não forçar a coleção inteira para ser avaliado.fonte
realized?
.realize
operação correspondenterealized?
.contains?
não se importam se você percebeu ou não o preguiçoso seq, isso responde à pergunta específica conforme feita, mas menos ao título da pergunta.Isso é até certo ponto uma questão de taxonomia. uma sequência preguiçosa é apenas um tipo de sequência, assim como uma lista, vetor ou mapa. Portanto, a resposta é, claro, "depende do tipo de sequência não preguiçosa que você deseja obter:
Escolha entre:
(doall ... )
(apply list (my-lazy-seq)) OR (into () ...)
(vec (my-lazy-seq))
Você pode ter qualquer tipo de sequência que mais atenda às suas necessidades.
fonte
(vec (my-lazy-seq))
não é tão bom em situações como as seguintes:(vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]]
Visto quecheshire
opta por produzir um seq preguiçoso de(json/parse-string)
(json/parse-string-strict)
Esse cara rico parece saber seu clojure e está absolutamente certo.
Mas acho que este snippet de código, usando seu exemplo, pode ser um complemento útil para esta pergunta:
Na verdade, o tipo não mudou, mas a realização mudou
fonte
realized?
retornartrue
. Por exemplo(let [r (range) r? (realized? r)] (doall (take 1 r)) [r? (realized? r)]) => [false true]
[true true]
Eu tropecei nesta postagem do blog sobre
doall
não ser recursivo. Para isso, descobri que o primeiro comentário no post funcionou. Algo na linha de:Achei isso útil em um teste de unidade em que queria forçar a avaliação de alguns aplicativos aninhados
map
para forçar uma condição de erro.fonte
fonte