Sự khác biệt giữa liều lượng và for in Clojure là gì? Một số ví dụ về thời điểm bạn muốn sử dụng cái này thay cho cái kia là gì?
Sự khác biệt giữa liều lượng và for in Clojure là gì? Một số ví dụ về thời điểm bạn muốn sử dụng cái này thay cho cái kia là gì?
Câu trả lời:
Sự khác biệt là for
xây dựng một chuỗi lười biếng và trả về nó trong khi doseq
thực hiện các hiệu ứng phụ và trả về 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
Nếu bạn muốn tạo một chuỗi mới dựa trên các chuỗi khác, hãy sử dụng for. Nếu bạn muốn thực hiện các hiệu ứng phụ (in, ghi vào cơ sở dữ liệu, phóng đầu đạn hạt nhân, v.v.) dựa trên các yếu tố từ một số chuỗi, hãy sử dụng liều lượngq.
Cũng lưu ý rằng doseq
háo hức trong khi for
lười biếng. Ví dụ bị thiếu trong câu trả lời của Rayne là
(for [x [1 2 3]] (println x))
Ở REPL, điều này nói chung sẽ làm những gì bạn muốn, nhưng về cơ bản đó là một sự trùng hợp: REPL buộc chuỗi lười được tạo ra for
, khiến các printlns xảy ra. Trong môi trường không tương tác, không có gì sẽ được in. Bạn có thể thấy điều này thực tế bằng cách so sánh kết quả của
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
Vì def
biểu mẫu trả về var mới được tạo chứ không phải giá trị được liên kết với nó, nên không có gì để REPL in và lazy
sẽ tham chiếu đến một lazy-seq chưa được thực hiện: không có phần tử nào của nó được tính toán cả. eager
sẽ tham chiếu đến nil
, và tất cả việc in ấn của nó sẽ được thực hiện.