Answers:
区别在于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。
还请注意,懒惰时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
表单返回的是新创建的var,而不是绑定的值,所以REPL没有要打印的内容,并且lazy
将引用未实现的lazy-seq:根本没有计算任何元素。eager
将参考nil
,并且其所有打印都将完成。