Solución:
La diferencia es que for
construye una secuencia perezosa y la devuelve mientras doseq
es para ejecutar efectos secundarios y devuelve cero.
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 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
, provocando que se produzcan las impresiones. 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
Porque 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á a nil
, y se habrá realizado toda su impresión.