What's the difference between doseq and for in Clojure? What are some examples of when you would choose to use one over the other?
2 Answers
The difference is that for
builds a lazy sequence and returns it while doseq
is for executing side-effects and returns 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
If you want to build a new sequence based on other sequences, use for. If you want to do side-effects (printing, writing to a database, launching a nuclear warhead, etc) based on elements from some sequences, use doseq.

- 31,473
- 17
- 86
- 101
-
12now that are much side-effects ... launching a nuclear warhead :) – Marc Apr 08 '13 at 21:48
-
8Thanks! I had pulling my (long gone) hair with "for" that it never fire my nuclear warheads over my list of items. "doseq" sure did. – Yu Shen Jun 18 '14 at 10:23
Note also that doseq
is eager while for
is lazy. The example missing in Rayne's answer is
(for [x [1 2 3]] (println x))
At the REPL, this will generally do what you want, but that's basically a coincidence: the REPL forces the lazy sequence produced by for
, causing the printlns to happen. In a non-interactive environment, nothing will ever be printed. You can see this in action by comparing the results of
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
Because the def
form returns the new var created, and not the value which is bound to it, there's nothing for the REPL to print, and lazy
will refer to an unrealized lazy-seq: none of its elements have been computed at all. eager
will refer to nil
, and all of its printing will have been done.

- 89,153
- 8
- 140
- 205
-
How does doseq handle evaluation of infinite lazy sequence? bad idea? only call it on finite sequences, either eager or lazy? – johnbakers Jan 25 '14 at 09:15
-
@johnbakers It will block forever until the evaluation is interrupted. Clojure never attempts to handle infinite sequences in a different way than finite sequences. – Resigned June 2023 Dec 22 '16 at 18:53
-
Printing the symbol 'lazy, which is the same name as the def, is really confusing. Use the string "lazy". – Klaus Wuestefeld Sep 24 '22 at 07:04