จะประเมินตัวแปรก่อนเพิ่มลงในรายการได้อย่างไร?


30

เห็นได้ชัดว่าด้านล่างใช้งานไม่ได้และด้วยเหตุนี้คำถามนี้

ฉันจะแก้ไขโค้ดด้านล่างเพื่อให้ค่าsomelistกลายเป็น'(("abc" . 123))อย่างไร

(setq x "abc")
(setq y 123)
(setq somelist nil)
(add-to-list 'somelist '(x . y))

5
คุณเคยลอง quasiquoting บ้างไหม? ลอง`(,x . ,y)ดู
แดน

อานั่นคือสิ่งที่ฉันพลาด ฉันไม่รู้ว่าจะใช้ google เพื่ออะไร :) ฉันพยายาม(add-to-list 'somelist '(,x . ,y))แต่ลืม backquote
Kaushal Modi

คำถามที่พิจารณาว่าซ้ำซ้อนของคำถามนี้เกิดขึ้นบ่อยมาก มีใครบางคนคิดวิธีที่จะทำให้ชัดเจนสำหรับผู้เริ่มต้นว่าคำถาม / คำตอบนี้คือสิ่งที่พวกเขากำลังมองหา? ฉันสงสัยว่าส่วนหนึ่งของปัญหาคือชื่อของคำถามนี้เหมาะสมถ้าคุณรู้สาเหตุของปัญหาแล้ว (เช่นคุณรู้คำตอบ) ฉันพยายามนึกภาพตัวเองในฐานะผู้ใช้ที่ไม่มีความคิดว่าตัวแปรต้องได้รับการประเมินและแม้แต่น้อยความคิดที่ว่า "เครื่องหมาย" หมายถึงอะไร แต่กำลังจะว่างเปล่า @Drew?
สเตฟาน

@stefan: ไม่เหมือนกับกรณีที่มีข้อความแสดงข้อผิดพลาด (ซึ่งสามารถใช้ในชื่อคำถามของชุมชน Q + A) ข้อผิดพลาดถ้ามีเป็นผลมาจากการอ้างถึงบางสิ่งที่ต้องได้รับการประเมิน (และนี่เป็นเฉพาะ กรณีของ) สามารถไกลไซต์ของข้อความ โดยทั่วไปจะไม่มีข้อผิดพลาด (Emacs) - พฤติกรรมที่ไม่สอดคล้องกับสิ่งที่ผู้ใช้ต้องการ
ดึง

@Stefan: ไม่มีชื่อคำถามที่ยอดเยี่ยมสำหรับเรื่องนี้ แต่อย่างน้อยเราสามารถกำหนดคำถามที่จัดการกับปัญหาโดยตรงซึ่งรวมถึงกรณี "ปกติ" ที่เรียกร้องให้ลบเครื่องหมายคำพูดและกรณีที่เรียกร้องให้เลิก quasiquoting Q ที่ดีครอบคลุมกรณีดังกล่าวและคำตอบที่ดีที่ครอบคลุมพวกเขาจะเป็นประโยชน์ แต่สำหรับการค้นหา Qs ที่ซ้ำกัน: หากไม่มีข้อความแสดงข้อผิดพลาดในชื่อ Q นั้นจำเป็นต้องอ่านคำถามทั้งหมดและรู้วิธีค้นหาสำเนาที่ชี้ไป
ดึง

คำตอบ:


30

ปัญหาทั่วไปคือคุณต้องxและได้รับการประเมินก่อนที่จะแทรกอยู่ในy somelistปัญหาของรายการที่ยกมา (พร้อมด้วย'ไวยากรณ์ผู้อ่าน)คือว่าquoteเป็นรูปแบบพิเศษที่ไม่ได้ประเมินอาร์กิวเมนต์ ตามเอกสาร:

(quote ARG)

ส่งคืนอาร์กิวเมนต์โดยไม่ประเมินค่า อัตราผลตอบแทน(quote x) xคำเตือน: quoteไม่สร้างค่าส่งคืน แต่เพียงส่งคืนค่าที่สร้างไว้ล่วงหน้าโดยตัวอ่าน Lisp ...

ดังนั้นคุณจะต้องแบ็คโคทหรือใช้ฟังก์ชั่นที่ประเมินข้อโต้แย้ง

Backquoting ช่วยให้คุณสามารถประเมินองค์ประกอบของรายการที่ยกมาเลือกด้วย,ไวยากรณ์:

(setq x "x-val" y "y-val" z "z-val" somelist nil)
'(x  y z)                            ; => (x y z)
`(x ,y z)                            ; => (x "y-val" z)
(add-to-list 'somelist `(x y ,z))    ; => ((x y "z-val"))

อีกวิธีหนึ่งคุณสามารถใช้cons(ตามที่ @tarsius แนะนำในคำตอบของเขา) หรือสำหรับองค์ประกอบจำนวนโดยพลการlist:

(add-to-list 'somelist (cons x y))   ; => (("x-val" . "y-val"))
(setq somelist nil)                  ; reset
(add-to-list 'somelist (list x y z)) ; => (("x-val" "y-val" "z-val"))

สิ่งที่จะใช้ขึ้นอยู่กับสิ่งที่คุณต้องทำกับองค์ประกอบ


19

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

ใช้รูปแบบที่สร้างเซลล์ข้อเสียจากสองค่าที่ประเมินแทนอาร์กิวเมนต์

(cons x y)

แน่นอนคุณสามารถ quasiquote แต่ที่ไม่เหมาะสมที่นี่จริงๆและดูแย่ลง ใช้`และ,เมื่อปรับปรุงการอ่านได้ง่ายเช่นเมื่อทำอะไรที่ซับซ้อนกว่าการสร้างเซลล์ข้อเสียหรือเพิ่มอะตอมหรือรายการที่จุดเริ่มต้นของรายการที่มีอยู่บางรายการ

การใช้ quasiquoting จะมีลักษณะเช่นนี้:

`(,x . ,y)

ซึ่งแย่กว่านั้นเพราะใช้ไวยากรณ์เพิ่มเติมซึ่งไม่จำเป็นเลยในกรณีนี้และทำให้งงที่consกำลังถูกใช้


3
จุดที่ดีในconsไอเอ็นจี Quasiquoting นัดฉันเป็นข้อมูลเพิ่มเติมเกี่ยวกับการควบคุมที่ละเอียดของเนื้อหารายการมากกว่าการอ่าน consแต่ผมเห็นว่าการใช้กรณีที่เหมาะสมสำหรับ
แดน

ขอบคุณสำหรับคำตอบ. นั่นเป็นช่วงเวลาที่ดีสำหรับฉัน ฉันใส่เครื่องหมายคำพูดก่อนรายการและข้อเสีย
Kaushal Modi

@ แดนใช่แล้ว - และไม่ Quasiquoting ไม่สามารถทำอะไรที่คุณไม่สามารถทำอะไรมีเพียงcons, และlist nconcยกเว้นคนที่สวยกว่า มันคือน้ำตาลซินแทคติคซึ่งมีประโยชน์เมื่อคุณต้องการ "การควบคุมเนื้อหารายการอย่างละเอียด" (ในขณะที่ "ทำอะไรที่ซับซ้อนกว่าการเพิ่มอะตอมหรือรายการที่จุดเริ่มต้น") และประโยชน์เพิ่มเติมของการใช้น้ำตาลซินแทคติคคือ: ความสามารถในการอ่าน การ quasiquoting ไม่ได้ให้การควบคุมที่ละเอียดยิ่งขึ้นไปอีก แต่ช่วยให้คุณทำสิ่งเดียวกันโดยมีข้อบกพร่องน้อยลงในการพยายามครั้งแรก :-)
tarsius
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.