เหตุใดจึงชอบ seq มากกว่าที่ไม่ว่างเปล่าเป็นเพรดิเคต

เอกสารสำหรับ empty? ระบุว่า "โปรดใช้สำนวน (seq x) แทนที่จะเป็น (ไม่ (ว่าง? x))" MisterMetaphor ชี้ให้เห็นว่าการใช้ seq เป็นภาคแสดงสามารถเข้าใจได้ เมื่อใช้ใน if-let:

(if-let [s (seq might-be-empty)]
   (fn-for-non-empty-seq s)
   (fn-for-empty-seq))

ฉันควรใช้ seq เพื่อทดสอบความไม่ว่างเปล่าโดยทั่วไปหรือไม่ seq อาจแปลงอาร์กิวเมนต์เป็นรูปแบบอื่น ตัวอย่างเช่น:

user=> (class (lazy-seq '(1 2 3)))
clojure.lang.LazySeq
user=> (class (seq (lazy-seq '(1 2 3))))
clojure.lang.PersistentList
user=> (class (map inc [1 2 3]))
clojure.lang.LazySeq
user=> (class (seq (map inc [1 2 3])))
clojure.lang.ChunkedCons

ดูเหมือนว่าจะเป็นการเสียเวลาหากเพียงต้องการทดสอบความว่างเปล่า และไม่จำเป็นต้องผูกใหม่ หรือถ้าฉันไม่ต้องการการแปลงก่อนการเชื่อมโยง not-empty จะไม่เป็นทางเลือกที่ดีกว่าในกรณีเช่นนี้ใช่หรือไม่ จะส่งกลับ nil หากอาร์กิวเมนต์ว่างเปล่า และอาร์กิวเมนต์ไม่เปลี่ยนแปลงหากไม่ว่างเปล่า

(if (not-empty [])
  "more to do"
  "all done")

person Mars    schedule 06.02.2014    source แหล่งที่มา


คำตอบ (1)


ขั้นแรก ตรวจสอบคำจำกัดความของ empty?:

(defn empty?
  "Returns true if coll has no items - same as (not (seq coll)).
  Please use the idiom (seq x) rather than (not (empty? x))"
  {:added "1.0"
  :static true}
  [coll] (not (seq coll)))

ดังนั้น empty? คือ (not (seq coll)) นั่นเป็นเหตุผลว่าทำไมจึงไม่สนับสนุนที่จะเสริม empty? เพราะคุณกำลังทำการปฏิเสธสองครั้งใน seq

ตอนนี้ดู not-empty

(defn not-empty
  "If coll is empty, returns nil, else coll"
  {:added "1.0"
   :static true}
  [coll] (when (seq coll) coll))

แปลกใจที่มันใช้ seq เป็นการทดสอบความไม่ว่างเปล่าเช่นกัน not-empty นี้มีประโยชน์หากประเภทมีความสำคัญ -- nth ประสิทธิภาพของเวกเตอร์, conj พฤติกรรม ฯลฯ -- เนื่องจากจะส่งกลับการเรียงลำดับที่ไม่ว่างเปล่าตามที่เป็นอยู่ ใช้เป็นเพียงภาคแสดง แต่จะเป็นเพียงการล้อม seq

อย่ากังวลว่า seq จะมือหนัก มันทำได้มากกว่าการส่งคืนตัววนซ้ำเล็กน้อย มันไม่ได้แปลงโครงสร้างข้อมูลทั้งหมดจริงๆ

person A. Webb    schedule 06.02.2014
comment
ขอบคุณ. น่าทึ่งและน่าประหลาดใจที่ต้องจ่ายค่าใช้จ่ายเพิ่มเติมใดๆ (การส่งคืนตัววนซ้ำ) สำหรับการดำเนินการที่ใช้บ่อยขนาดนี้ หรือค่อนข้างจะเป็นว่าในความเป็นจริงมันไม่มีค่าใช้จ่ายเลยซึ่งก็น่าทึ่งอีกครั้ง - person Mars; 06.02.2014
comment
ฉันหวังว่าคอมไพเลอร์ JIT จะไม่มีปัญหาในการปรับการปฏิเสธสองครั้งให้เหมาะสม - person remcycles; 19.06.2018
comment
@ remicles2 ฉันไม่สามารถจินตนาการถึงการปรับให้เหมาะสมในภาษาที่พิมพ์แบบไดนามิกด้วยแฟรกเมนต์ขี้เกียจที่จะร้อนแรงขนาดนั้น มีรายงานใดบ้างที่บอกว่า JIT สามารถทำได้มากเพียงใดก่อนที่จะพบกับอุปสรรคสำคัญ - person David Tonhofer; 18.05.2019