剂量q和Clojure之间的差异

Jef*_*ear 100 clojure

doseq和Clojure之间有什么区别?什么时候你选择使用一个而不是另一个?

Ray*_*yne 159

不同之处在于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
Run Code Online (Sandbox Code Playgroud)

如果要基于其他序列构建新序列,请使用for.如果您想根据某些序列中的元素进行副作用(打印,写入数据库,发射核弹头等),请使用doseq.

  • 现在有很多副作用......发射核弹头:) (11认同)
  • 谢谢!我用"for"来拉我的(已经很久)头发,它从来没有把我的核弹头射到我的物品清单上."doseq"确实做到了. (6认同)

ama*_*loy 56

还要注意,这是懒惰时的doseq渴望for.Rayne的回答中缺少的例子是

(for [x [1 2 3]] (println x))
Run Code Online (Sandbox Code Playgroud)

在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
Run Code Online (Sandbox Code Playgroud)

因为def表单返回创建的新var,而不是绑定到它的值,所以REPL没有任何内容可以打印,并且lazy将引用一个未实现的lazy-seq:根本没有计算任何元素.eager将参考nil,并且它的所有印刷都将完成.