Sự khác biệt giữa liều lượng và for trong Clojure


105

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:


167

Sự khác biệt là forxây dựng một chuỗi lười biếng và trả về nó trong khi doseqthự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.


11
bây giờ đó là nhiều tác dụng phụ ... phóng một đầu đạn hạt nhân :)
Marc

6
Cảm ơn! Tôi đã kéo mái tóc (đã lâu) của mình để "cho" rằng nó không bao giờ bắn đầu đạn hạt nhân của tôi trên danh sách các mặt hàng của tôi. "Liều lượng" chắc chắn đã làm.
Yu Shen

Đây là một cách tuyệt vời để phân biệt.
jskulski

60

Cũng lưu ý rằng doseqháo hức trong khi forlườ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

defbiể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à lazysẽ 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ả. eagersẽ tham chiếu đến nil, và tất cả việc in ấn của nó sẽ được thực hiện.


Liềuq xử lý đánh giá chuỗi lười biếng vô hạn như thế nào? ý kiến ​​tồi? chỉ gọi nó trên chuỗi hữu hạn, háo hức hoặc lười biếng?
johnbakers

@johnbakers Nó sẽ chặn vĩnh viễn cho đến khi quá trình đánh giá bị gián đoạn. Clojure không bao giờ cố gắng xử lý chuỗi vô hạn theo một cách khác với chuỗi hữu hạn.
Radon Rosborough
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.