lazy-evaluation - Cómo convertir secuencias perezosas a no perezosas en Clojure





(6)


Esto es hasta cierto punto una cuestión de taxonomía. una secuencia floja es solo un tipo de secuencia, como una lista, un vector o un mapa. Entonces, la respuesta es, por supuesto, "depende del tipo de secuencia no lenta que desee obtener:
Elija entre:

  • una secuencia floja ex perezoso (totalmente evaluado) (doall ... )
  • una lista para el acceso secuencial (apply list (my-lazy-seq)) OR (into () ...)
  • un vector para acceso aleatorio posterior (vec (my-lazy-seq))
  • un mapa o un conjunto si tiene algún propósito especial.

Puede tener cualquier tipo de secuencia que la mayoría de las suites necesite.

Intenté lo siguiente en Clojure, esperando tener la clase de una secuencia no lenta devuelta:

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

Sin embargo, esto todavía devuelve clojure.lang.LazySeq . Mi suposición es que doall no evalúa la secuencia completa, pero devuelve la secuencia original, ya que aún es útil para la memorización.

Entonces, ¿cuál es el medio idiomático de crear una secuencia no perezosa desde una floja?




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:

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

De hecho, el tipo no ha cambiado, pero la realización ha




Me encontré con esta blog este blog acerca de que no todos son recursivos. Para eso, encontré el primer comentario en la publicación que hizo el truco. Algo como:

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

Encontré esto útil en una prueba unitaria donde quería forzar la evaluación de algunas aplicaciones anidadas del map para forzar una condición de error.




doall es todo lo que necesitas. Solo porque el seq tenga tipo LazySeq no significa que tenga una evaluación pendiente. Lazy seqs almacena en la caché sus resultados, por lo que todo lo que tienes que hacer es caminar lazy seq una vez (como doall hace) para forzarlo todo, y así hacerlo no perezoso. seq no fuerza a toda la colección a ser evaluada.




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



Scala

Scala evolucionó a partir de un lenguaje funcional puro conocido como Funnel y representa una implementación de sala limpia de casi toda la sintaxis de Java, diferenciándose solo en los casos en que se podría realizar una mejora clara o en la que comprometería la naturaleza funcional del lenguaje. Estas diferencias incluyen objetos singleton en lugar de métodos estáticos e inferencia de tipos.

Gran parte de esto se basó en el trabajo previo de Martin Odersky con el lenguaje de Pizza . La integración OO / FP va mucho más allá de los meros cierres y ha llevado a que el lenguaje se describa como post-funcional.

A pesar de esto, es lo más cercano a Java de muchas maneras. Principalmente debido a una combinación de soporte OO y tipificación estática, pero también debido a un objetivo explícito en el diseño del lenguaje que debe integrarse muy estrechamente con Java.

Maravilloso

Groovy aborda explícitamente dos de las mayores críticas de Java por

  • se escribe de forma dinámica, lo que elimina una gran cantidad de repetitivo y
  • Añadiendo cierres al lenguaje.

Quizás sea sintácticamente más cercano a Java, no ofrece algunas de las construcciones funcionales más ricas que proporcionan Clojure y Scala, pero sigue ofreciendo una mejora evolutiva definitiva, especialmente para escribir programas de scripts.

Groovy tiene el respaldo comercial más sólido de los tres idiomas, principalmente a través de springsource.

Clojure

Clojure es un lenguaje funcional en la familia LISP, también se escribe dinámicamente.

Las características como el soporte STM le dan el mejor soporte de concurrencia listo para usar , mientras que Scala requiere una biblioteca de terceros como Akka para duplicar esto.

Sintácticamente, también es el más alejado de los tres lenguajes del código típico de Java.

También tengo que revelar que estoy más familiarizado con Scala :)







clojure lazy-evaluation