Apa perbedaan antara doseq dan untuk di Clojure? Apa saja contoh ketika Anda akan memilih untuk menggunakan salah satu dari yang lain?
Apa perbedaan antara doseq dan untuk di Clojure? Apa saja contoh ketika Anda akan memilih untuk menggunakan salah satu dari yang lain?
Jawaban:
Perbedaannya adalah bahwa formembangun urutan malas dan mengembalikannya saat dosequntuk menjalankan efek samping dan mengembalikan nol.
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
Jika Anda ingin membuat urutan baru berdasarkan urutan lain, gunakan untuk. Jika Anda ingin melakukan efek samping (mencetak, menulis ke database, meluncurkan hulu ledak nuklir, dll) berdasarkan elemen dari beberapa urutan, gunakan doseq.
Perhatikan juga yang doseqbersemangat saat forsedang malas. Contoh yang hilang dalam jawaban Rayne adalah
(for [x [1 2 3]] (println x))
Di REPL, ini biasanya akan melakukan apa yang Anda inginkan, tetapi itu pada dasarnya kebetulan: REPL memaksa urutan malas yang dihasilkan oleh for, menyebabkan printlns terjadi. Dalam lingkungan non-interaktif, tidak ada yang akan dicetak. Anda dapat melihat ini beraksi dengan membandingkan hasil
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
Karena defformulir mengembalikan var baru yang dibuat, dan bukan nilai yang terikat padanya, REPL tidak akan mencetak apa pun, dan lazyakan merujuk ke lazy-seq yang belum direalisasi: tidak ada elemennya yang telah dihitung sama sekali. eagerakan merujuk ke nil, dan semua pencetakannya akan selesai.