Разница между доза и в Clojure - PullRequest
99 голосов
/ 18 января 2011

Какая разница между доза-к и в клоуре? Какие примеры того, когда вы решили использовать один поверх другого?

Ответы [ 2 ]

153 голосов
/ 18 января 2011

Разница в том, что 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.

56 голосов
/ 13 марта 2011

Обратите внимание, что doseq стремится, а for ленится. Пример, отсутствующий в ответе Рэйна:

(for [x [1 2 3]] (println x))

В REPL это обычно будет делать то, что вы хотите, но это в основном совпадение: REPL заставляет ленивую последовательность, генерируемую for, вызывать печать printlns. В неинтерактивной среде ничего не будет напечатано. Вы можете увидеть это в действии, сравнив результаты

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 возвращает созданную новую переменную, а не значение, связанное с ней, REPL ничего не печатает, и lazy будет ссылаться на нереализованный lazy-seq: ни один из его элементов были вычислены на всех. eager будет ссылаться на nil, и вся его печать будет выполнена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...