¿Cuál es la diferencia entre doseq y for en Clojure? ¿Cuáles son algunos ejemplos de cuándo elegiría usar uno sobre el otro?
¿Cuál es la diferencia entre doseq y for en Clojure? ¿Cuáles son algunos ejemplos de cuándo elegiría usar uno sobre el otro?
Respuestas:
La diferencia es que for
crea una secuencia diferida y la devuelve mientras doseq
es para ejecutar efectos secundarios y devuelve nil.
user=> (for [x [1 2 3]] (+ x 5))
(6 7 8)
user=> (doseq [x [1 2 3]] (+ x 5))
nil
user=> (doseq [x [1 2 3]] (println x))
1
2
3
nil
Si desea crear una nueva secuencia basada en otras secuencias, use for. Si desea hacer efectos secundarios (imprimir, escribir en una base de datos, lanzar una ojiva nuclear, etc.) basados en elementos de algunas secuencias, use doseq.
Tenga en cuenta también que doseq
está ansioso mientras que for
es perezoso. El ejemplo que falta en la respuesta de Rayne es
(for [x [1 2 3]] (println x))
En el REPL, esto generalmente hará lo que quieras, pero eso es básicamente una coincidencia: el REPL fuerza la secuencia perezosa producida por for
, lo que hace que suceda la impresión. En un entorno no interactivo, nunca se imprimirá nada. Puede ver esto en acción comparando los resultados de
user> (def lazy (for [x [1 2 3]] (println 'lazy x)))
#'user/lazy
user> (def eager (doseq [x [1 2 3]] (println 'eager x)))
eager 1
eager 2
eager 3
#'user/eager
Debido a que el def
formulario devuelve la nueva var creada, y no el valor que está vinculado a ella, no hay nada para que el REPL imprima y lazy
se referirá a un lazy-seq no realizado: ninguno de sus elementos se ha calculado en absoluto. eager
se referirá nil
, y se habrá realizado toda su impresión.