回答:
違いは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では、これは通常、あなたが望むことを行いますが、それは基本的に偶然ですfor
。REPLは、によって生成される遅延シーケンスを強制し、printlnを発生させます。非インタラクティブ環境では、何も印刷されません。の結果を比較することで、これを実際に見ることができます
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
未実現怠惰-seqのを参照します。その要素のどれもがすべてで計算されていません。eager
はを参照しnil
、その印刷はすべて行われます。