ความแตกต่างระหว่าง doseq และ for ใน Clojure


106

อะไรคือความแตกต่างระหว่าง doseq และ for ใน Clojure? มีตัวอย่างอะไรบ้างที่คุณจะเลือกใช้แบบอื่น

คำตอบ:


168

ความแตกต่างคือการforสร้างลำดับที่ขี้เกียจและส่งกลับในขณะที่ใช้doseqสำหรับการเรียกใช้ผลข้างเคียงและส่งกลับศูนย์

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

หากคุณต้องการสร้างลำดับใหม่โดยยึดตามลำดับอื่นให้ใช้สำหรับ. หากคุณต้องการทำเอฟเฟกต์ข้างเคียง (การพิมพ์การเขียนไปยังฐานข้อมูลการเปิดตัวหัวรบนิวเคลียร์ ฯลฯ ) ตามองค์ประกอบจากลำดับบางส่วนให้ใช้ doseq


11
ตอนนี้มีผลข้างเคียงมาก ... การเปิดตัวหัวรบนิวเคลียร์ :)
Marc

6
ขอบคุณ! ฉันดึงผม (หายไปนาน) ของฉันด้วย "สำหรับ" ที่มันไม่เคยยิงหัวรบนิวเคลียร์ของฉันเหนือรายการสิ่งของของฉัน "doseq" ได้แน่นอน
Yu Shen

นี่เป็นวิธีที่ดีในการสร้างความแตกต่าง
jskulski

60

สังเกตด้วยว่าdoseqกระตือรือร้นในขณะที่forขี้เกียจ ตัวอย่างที่ขาดหายไปในคำตอบของ Rayne คือ

(for [x [1 2 3]] (println x))

ที่ REPL โดยทั่วไปสิ่งนี้จะทำในสิ่งที่คุณต้องการ แต่โดยพื้นฐานแล้วเป็นเรื่องบังเอิญ: REPL บังคับให้ลำดับขี้เกียจที่เกิดขึ้นforทำให้ printlns เกิดขึ้น ในสภาพแวดล้อมที่ไม่โต้ตอบจะไม่มีการพิมพ์อะไรเลย คุณสามารถเห็นสิ่งนี้ในการดำเนินการโดยเปรียบเทียบผลลัพธ์ของ

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

เนื่องจากdefแบบฟอร์มส่งคืน var ใหม่ที่สร้างขึ้นไม่ใช่ค่าที่ถูกผูกไว้จึงไม่มีสิ่งใดให้ REPL พิมพ์และlazyจะอ้างถึง lazy-seq ที่ยังไม่เกิดขึ้น: ไม่มีการคำนวณองค์ประกอบใด ๆ เลย eagerจะอ้างถึงnilและการพิมพ์ทั้งหมดจะเสร็จสิ้น


doseq จัดการการประเมินลำดับความขี้เกียจที่ไม่มีที่สิ้นสุดอย่างไร คิดไม่ดี? เรียกมันเฉพาะในลำดับที่ จำกัด ไม่ว่าจะกระตือรือร้นหรือขี้เกียจ?
johnbakers

@johnbakers จะบล็อกตลอดไปจนกว่าการประเมินจะถูกขัดจังหวะ Clojure ไม่เคยพยายามจัดการลำดับที่ไม่มีที่สิ้นสุดด้วยวิธีที่แตกต่างจากลำดับที่ จำกัด
Radon Rosborough
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.