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 foreine verzögerte Sequenz erstellt und zurückgegeben wird, während doseqNebenwirkungen 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 doseqeifrig ist, während forfaul 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 defFormular die neu erstellte Variable und nicht den daran gebundenen Wert zurückgibt, kann die REPL nichts drucken und lazyverweist auf eine nicht realisierte Lazy-Seq: Keines ihrer Elemente wurde überhaupt berechnet. eagerwird sich darauf beziehen nil, und der gesamte Druck wurde durchgeführt.