Was ist der Unterschied zwischen doseq und for in Clojure? Was sind einige Beispiele dafür, wann Sie eines über dem anderen verwenden würden?
Was ist der Unterschied zwischen doseq und for in Clojure? Was sind einige Beispiele dafür, wann Sie eines über dem anderen verwenden würden?
Antworten:
Der Unterschied besteht darin, dass for
eine verzögerte Sequenz erstellt und zurückgegeben wird, während doseq
Nebenwirkungen ausgeführt werden, und Null zurückgegeben wird.
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
Wenn Sie eine neue Sequenz basierend auf anderen Sequenzen erstellen möchten, verwenden Sie für. Wenn Sie Nebenwirkungen (Drucken, Schreiben in eine Datenbank, Starten eines Atomsprengkopfs usw.) basierend auf Elementen aus einigen Sequenzen verursachen möchten, verwenden Sie doseq.
Beachten Sie auch, dass doseq
eifrig ist, während for
faul ist. Das Beispiel, das in Raynes Antwort fehlt, ist
(for [x [1 2 3]] (println x))
Bei der REPL wird dies im Allgemeinen das tun, was Sie wollen, aber das ist im Grunde ein Zufall: Die REPL erzwingt die von erzeugte verzögerte Sequenz for
, wodurch die Druckvorgänge ausgeführt werden. In einer nicht interaktiven Umgebung wird niemals etwas gedruckt. Sie können dies in Aktion sehen, indem Sie die Ergebnisse von vergleichen
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
Da das def
Formular die neu erstellte Variable und nicht den daran gebundenen Wert zurückgibt, kann die REPL nichts drucken und lazy
verweist auf eine nicht realisierte Lazy-Seq: Keines ihrer Elemente wurde überhaupt berechnet. eager
wird sich darauf beziehen nil
, und der gesamte Druck wurde durchgeführt.