อะไรคือความแตกต่างระหว่าง doseq และ for ใน Clojure? มีตัวอย่างอะไรบ้างที่คุณจะเลือกใช้แบบอื่น
อะไรคือความแตกต่างระหว่าง doseq และ for ใน Clojure? มีตัวอย่างอะไรบ้างที่คุณจะเลือกใช้แบบอื่น
คำตอบ:
ความแตกต่างคือการ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
สังเกตด้วยว่า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
และการพิมพ์ทั้งหมดจะเสร็จสิ้น