ให้ ไม่ดำเนินการนิพจน์ที่สองในร่างกาย

หากฉันเข้าใจเอกสารประกอบถูกต้อง ฉันสามารถเขียนสิ่งนี้ได้:

(let [a 5 b 10]
  (print a)
  (print b))

ใช้งานได้ตามที่คาดไว้และพิมพ์ออกมา 5 และ 10 ฉันใช้กลไกนี้ในข้อมูลโค้ดนี้ (โค้ดเต็มคือ ที่นี่ หากคุณต้องการการอ้างอิงเพิ่มเติม):

(defn create! [fields]
  (let [username (user/unique-user (:author fields))
        competition-id (:id (competition/latest))]
    (if-not (exists? (:ld_uid fields))
      (insert entries (values {
                               :ld_uid (:ld_uid fields)
                               :title (:title fields)
                               :description (:description fields)
                               :type (:type fields)
                               :user_id (:id username)
                               :competition_id competition-id})))
    (for [link (:links fields)]
      (source/create! (:id (by-ld-uid (:ld_uid fields))) (:url link) (:title link)))))

ปัญหาคือ นิพจน์ for ไม่ได้ดำเนินการ คำสั่งที่เป็นของตัวเองทำงานได้ตามที่คาดไว้ แต่ในโค้ดนี้เหนือนิพจน์ insert จะถูกดำเนินการ แต่ for ไม่ใช่ ฉันดูแลบางสิ่งบางอย่างหรือไม่? ฉันไม่มีความคิดว่าจะเกิดอะไรขึ้นที่นี่ :(


person Fu86    schedule 27.01.2014    source แหล่งที่มา
comment
นิพจน์ for เป็นแบบขี้เกียจ ล้อมด้วย dorun หรือเปลี่ยนเป็น doseq   -  person A. Webb    schedule 27.01.2014


คำตอบ (1)


ปัญหาไม่ใช่สิ่งที่คุณคิด: for ของ Clojure ใช้การประเมินแบบสันหลังยาว นั่นคือ ถ้าคุณไม่ทำอะไรกับสิ่งที่ส่งคืน การวนซ้ำจะไม่ทำงาน

นั่นมีประโยชน์มากสำหรับการวนซ้ำระยะยาวในลำดับขนาดใหญ่ที่คุณไม่ต้องการทั้งหมดด้วยซ้ำ แต่เมื่อคุณพยายามเรียกใช้ผลข้างเคียงจริงๆ การประเมินแบบ Lazy เป็นสิ่งที่คุณต้องหลีกเลี่ยง

คุณต้องการใช้ doseq แทน (http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/doseq)

person Max Noel    schedule 27.01.2014
comment
ขอบคุณ นั่นช่วยได้มาก! - person Fu86; 28.01.2014