Разница между доза и в Clojure
В чем разница между dosq и for в Clojure? Какие примеры того, когда вы решили использовать один поверх другого?
2 ответа
Разница в том, что for
создает ленивую последовательность и возвращает ее, пока doseq
для выполнения побочных эффектов и возвращает ноль.
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
Если вы хотите построить новую последовательность на основе других последовательностей, используйте для. Если вы хотите создавать побочные эффекты (печать, запись в базу данных, запуск ядерной боеголовки и т. Д.) На основе элементов некоторых последовательностей, используйте доза q.
Обратите внимание, что doseq
в то время как for
ленивый Пример, отсутствующий в ответе Рэйна:
(for [x [1 2 3]] (println x))
В REPL это обычно будет делать то, что вы хотите, но это в основном совпадение: REPL вызывает ленивую последовательность, создаваемую for
, в результате чего произойдет печать. В неинтерактивной среде ничего не будет напечатано. Вы можете увидеть это в действии, сравнив результаты
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
Поскольку def
form возвращает созданную новую переменную, а не значение, связанное с ней, REPL ничего не печатает, и lazy
будет ссылаться на нереализованный lazy-seq: ни один из его элементов не был вычислен вообще. eager
будет ссылаться на nil
и вся его печать будет сделана.