Intenté lo siguiente en Clojure, esperando que se devolviera la clase de una secuencia no perezosa:
(.getClass (doall (take 3 (repeatedly rand))))
Sin embargo, esto todavía regresa clojure.lang.LazySeq
. Supongo que doall
sí evalúa la secuencia completa, pero devuelve la secuencia original ya que sigue siendo útil para la memorización.
Entonces, ¿cuál es el medio idiomático de crear una secuencia no perezosa a partir de una perezosa?
clojure
lazy-evaluation
Tim Clemons
fuente
fuente
doall
(vec (take 3 (repeatedly rand)))
Respuestas:
doall
es todo lo que necesitas. El hecho de que elseq
tipo hasLazySeq
no significa que tenga una evaluación pendiente. Los perezososseq
almacenan en caché sus resultados, por lo que todo lo que necesita hacer es caminar el perezososeq
una vez (como lodoall
hace) para forzarlo todo y, por lo tanto, convertirlo en no perezoso.seq
no no forzar la colección entera a ser evaluado.fuente
realized?
.realize
operación que coincidarealized?
.contains?
no importa si se dio cuenta de la secuencia perezosa o no, esto responde a la pregunta específica tal como se le preguntó, pero menos al título de la pregunta.Hasta cierto punto, se trata de una cuestión de taxonomía. una secuencia perezosa es solo un tipo de secuencia como lo es una lista, vector o mapa. Entonces, la respuesta es, por supuesto, "depende del tipo de secuencia no perezosa que desee obtener:
elija entre:
(doall ... )
(apply list (my-lazy-seq)) OR (into () ...)
(vec (my-lazy-seq))
Puede tener cualquier tipo de secuencia que se adapte a sus necesidades.
fuente
(vec (my-lazy-seq))
no es tan agradable en situaciones como las siguientes:(vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]]
Dado quecheshire
elige producir una(json/parse-string)
(json/parse-string-strict)
Este tipo rico parece conocer su clojure y tiene toda la razón.
Pero creo que este fragmento de código, usando su ejemplo, podría ser un complemento útil para esta pregunta:
De hecho, el tipo no ha cambiado, pero la realización ha
fuente
realized?
regresartrue
. Por ejemplo(let [r (range) r? (realized? r)] (doall (take 1 r)) [r? (realized? r)]) => [false true]
[true true]
Me encontré con esta publicación de este blog sobre
doall
no ser recursivo. Por eso encontré que el primer comentario en la publicación hizo el truco. Algo parecido a:Encontré esto útil en una prueba unitaria en la que quería forzar la evaluación de algunas aplicaciones anidadas
map
para forzar una condición de error.fuente
fuente