2011-01-18 6 views

答えて

141

違いは、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を使います。

+0

偉大な答え。ありがとう! –

+9

これは多くの副作用です...核弾頭を起動する:) – Marc

+4

ありがとう!私は私の(長く消えた)髪の毛を "for"で引っ張ってきたので、私の核弾頭は決して私のアイテムのリストには射しませんでした。 "doseq"は確かにしました。 –

51

または熱心ですが、forは遅延しています。レインの答えに欠けている例は、REPLで

(for [x [1 2 3]] (println x)) 

あり、これは一般的に、あなたがやりたいだろうが、それは基本的には偶然の一致だ:REPLはprintlnsが起こることを引き起こして、forによって生成怠惰なシーケンスを強制します。非対話環境では、何も印刷されません。 defフォームが新しい作成var、およびないそれにバインドされている値を返しますので、あなたは、REPLを印刷するための何もない、

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 

の結果を比較することによって、この動作を確認することができ、かつlazyが参照されます実現されていないlazy-seq:その要素はまったく計算されていません。 eagernilを参照し、そのすべての印刷が完了しています。

+0

doseqは無限レイジーシーケンスの評価をどのように扱いますか?悪いアイデア?それを熱意か怠惰の有限シーケンスでしか呼び出せませんか? – johnbakers

+0

@johnbakers評価が中断されるまで永遠にブロックされます。 Clojureは有限シーケンスとは異なる方法で無限シーケンスを処理することはありません。 –

関連する問題