В чем разница между DoSq и for в Clojure? Каковы примеры того, когда вы бы предпочли использовать одно вместо другого?
106
Разница в том, что for
строит ленивую последовательность и возвращает ее, а doseq
предназначена для выполнения побочных эффектов и возвращает 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
Если вы хотите создать новую последовательность на основе других последовательностей, используйте for. Если вы хотите создать побочные эффекты (печать, запись в базу данных, запуск ядерной боеголовки и т. Д.) На основе элементов из некоторых последовательностей, используйте дозу.
Также обратите внимание, что
doseq
любит, когдаfor
ленится. Пример, отсутствующий в ответе Рейна:В REPL это обычно будет делать то, что вы хотите, но это в основном совпадение: REPL заставляет ленивую последовательность
for
, созданную с помощью , вызывая выполнение printlns. В неинтерактивной среде ничего не будет напечатано. Вы можете увидеть это в действии, сравнив результатыПоскольку
def
форма возвращает созданную новую переменную, а не значение, которое к ней привязано, REPL нечего печатать иlazy
будет ссылаться на нереализованный lazy-seq: ни один из его элементов не был вычислен вообще.eager
будет ссылаться наnil
, и вся его печать будет выполнена.источник