หลังจากผ่านส่วนสำคัญของหนังสือ Lisp เบื้องต้นแล้วฉันยังไม่เข้าใจว่าฟังก์ชันตัวดำเนินการพิเศษ(quote)
(หรือเทียบเท่า'
) ทำหน้าที่อะไร แต่นี่เป็นรหัส Lisp ทั้งหมดที่ฉันเคยเห็น
มันทำอะไร?
หลังจากผ่านส่วนสำคัญของหนังสือ Lisp เบื้องต้นแล้วฉันยังไม่เข้าใจว่าฟังก์ชันตัวดำเนินการพิเศษ(quote)
(หรือเทียบเท่า'
) ทำหน้าที่อะไร แต่นี่เป็นรหัส Lisp ทั้งหมดที่ฉันเคยเห็น
มันทำอะไร?
คำตอบ:
คำตอบสั้น ๆ ข้ามกฎการประเมินเริ่มต้นและไม่ประเมินนิพจน์ (สัญลักษณ์หรือ s-exp) ส่งผ่านไปยังฟังก์ชันตรงตามที่พิมพ์
คำตอบแบบยาว: กฎการประเมินเริ่มต้น
เมื่อมีการเรียกใช้ฟังก์ชันปกติ (ฉันจะมาในภายหลัง) อาร์กิวเมนต์ทั้งหมดที่ส่งผ่านไปจะได้รับการประเมิน ซึ่งหมายความว่าคุณสามารถเขียนสิ่งนี้:
(* (+ a 2)
3)
ซึ่งจะประเมิน(+ a 2)
โดยการประเมินa
และ 2. ค่าของสัญลักษณ์a
จะถูกค้นหาในชุดการผูกตัวแปรปัจจุบันแล้วแทนที่ พูดว่าa
ปัจจุบันถูกผูกไว้กับค่า 3:
(let ((a 3))
(* (+ a 2)
3))
เราจะได้(+ 3 2)
+ จากนั้นเรียกใช้ใน 3 และ 2 ให้ผล 5 ตอนนี้ฟอร์มเดิมของเรา(* 5 3)
ให้ผล 15
อธิบายquote
แล้ว!
Alright ดังที่เห็นข้างต้นอาร์กิวเมนต์ทั้งหมดของฟังก์ชันจะได้รับการประเมินดังนั้นหากคุณต้องการส่งผ่านสัญลักษณ์ a
ไม่ใช่ค่าของมันคุณไม่ต้องการประเมินค่านั้น สัญลักษณ์เสียงกระเพื่อมสามารถเพิ่มเป็นสองเท่าเป็นค่าของมันและเครื่องหมายที่คุณในภาษาอื่น ๆ จะใช้สตริงเช่นคีย์ไปยังตารางแฮช
นี่คือที่quote
มาสมมติว่าคุณต้องการพล็อตการจัดสรรทรัพยากรจากแอปพลิเคชัน Python แต่ทำการพล็อตด้วย Lisp ให้แอป Python ของคุณทำสิ่งนี้:
print("'(")
while allocating:
if random.random() > 0.5:
print(f"(allocate {random.randint(0, 20)})")
else:
print(f"(free {random.randint(0, 20)})")
...
print(")")
ให้ผลลัพธ์ของคุณเป็นแบบนี้ (ค่อนข้างน่ารักเล็กน้อย):
'((allocate 3)
(allocate 7)
(free 14)
(allocate 19)
...)
จำสิ่งที่ฉันพูดถึงquote
("ติ๊ก") ที่ทำให้กฎเริ่มต้นใช้ไม่ได้? ดี. สิ่งที่จะเกิดขึ้นก็คือค่าของallocate
และfree
ถูกค้นหาและเราไม่ต้องการสิ่งนั้น ในเสียงกระเพื่อมของเราเราต้องการที่จะทำ:
(dolist (entry allocation-log)
(case (first entry)
(allocate (plot-allocation (second entry)))
(free (plot-free (second entry)))))
สำหรับข้อมูลที่ให้ไว้ข้างต้นจะมีการเรียกใช้ฟังก์ชันตามลำดับต่อไปนี้:
(plot-allocation 3)
(plot-allocation 7)
(plot-free 14)
(plot-allocation 19)
แต่ What About list
?
ดีบางครั้งคุณไม่ต้องการที่จะประเมินข้อโต้แย้ง สมมติว่าคุณมีฟังก์ชันที่ดีที่จัดการกับตัวเลขและสตริงและส่งคืนรายการผลลัพธ์ของ ... สิ่งต่างๆ เริ่มต้นที่ผิดพลาด:
(defun mess-with (number string)
'(value-of-number (1+ number) something-with-string (length string)))
Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))
เฮ้! นั่นไม่ใช่สิ่งที่เราต้องการ เราต้องการประเมินข้อโต้แย้งบางข้ออย่างคัดเลือกและปล่อยให้ข้อโต้แย้งอื่น ๆ เป็นสัญลักษณ์ ลอง # 2!
(defun mess-with (number string)
(list 'value-of-number (1+ number) 'something-with-string (length string)))
Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)
ไม่ใช่แค่quote
แต่backquote
ดีกว่าเยอะ! ดูเหมือนว่ารูปแบบนี้จะพบได้บ่อยในมาโคร (ส่วนใหญ่) ซึ่งมีไวยากรณ์พิเศษสำหรับการทำเช่นนั้น backquote:
(defun mess-with (number string)
`(value-of-number ,(1+ number) something-with-string ,(length string)))
มันเหมือนกับการใช้quote
แต่มีตัวเลือกในการประเมินข้อโต้แย้งบางอย่างอย่างชัดเจนโดยนำหน้าด้วยลูกน้ำ ผลลัพธ์จะเทียบเท่ากับการใช้list
แต่ถ้าคุณสร้างโค้ดจากมาโครคุณมักจะต้องการประเมินเฉพาะส่วนเล็ก ๆ ของโค้ดที่ส่งคืนดังนั้น backquote จึงเหมาะสมกว่า สำหรับรายการที่สั้นลงlist
สามารถอ่านได้มากขึ้น
เฮ้คุณลืมquote
!
แล้วสิ่งนี้จะทิ้งเราไว้ที่ไหน? โอ้ใช่สิ่งที่ทำquote
จริง? เพียงแค่ส่งกลับอาร์กิวเมนต์ที่ไม่ได้ประเมิน! จำสิ่งที่ฉันพูดในตอนต้นเกี่ยวกับฟังก์ชันปกติได้หรือไม่? ปรากฎว่าตัวดำเนินการ / ฟังก์ชันบางอย่างไม่จำเป็นต้องประเมินข้อโต้แย้งของตน เช่น IF - คุณคงไม่ต้องการให้สาขาอื่นได้รับการประเมินหากไม่ได้ดำเนินการใช่ไหม? ที่เรียกว่าตัวดำเนินการพิเศษร่วมกับมาโครทำงานเช่นนั้น นอกจากนี้ตัวดำเนินการพิเศษยังเป็น "สัจพจน์" ของภาษาซึ่งเป็นชุดของกฎขั้นต่ำซึ่งคุณสามารถใช้ Lisp ที่เหลือได้โดยการรวมเข้าด้วยกันในรูปแบบต่างๆ
กลับไปที่quote
แม้ว่า:
Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL
Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL
เปรียบเทียบกับ (บน Steel-Bank Common Lisp):
Lisp> spiffy-symbol
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING {A69F6A9}>:
The variable SPIFFY-SYMBOL is unbound.
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-INT:SIMPLE-EVAL-IN-LEXENV SPIFFY-SYMBOL #<NULL-LEXENV>)
0]
เพราะไม่มีspiffy-symbol
ในขอบเขตปัจจุบัน!
สรุป
quote
, backquote
(พร้อมลูกน้ำ) และlist
เป็นเครื่องมือบางอย่างที่คุณใช้สร้างรายการซึ่งไม่เพียง แต่เป็นรายการค่าเท่านั้น แต่อย่างที่คุณเห็นสามารถใช้เป็นแบบน้ำหนักเบา (ไม่จำเป็นต้องกำหนด a struct
) โครงสร้างข้อมูล!
หากคุณต้องการเรียนรู้เพิ่มเติมขอแนะนำหนังสือPractical Common Lispของ Peter Seibel สำหรับแนวทางปฏิบัติในการเรียนรู้ Lisp หากคุณชอบเขียนโปรแกรมเป็นจำนวนมากอยู่แล้ว ในการเดินทาง Lisp ของคุณในที่สุดคุณจะเริ่มใช้แพ็คเกจด้วย Ron Garret's The Idiot's Guide to Common Lisp Packagesจะให้คำอธิบายที่ดีเกี่ยวกับสิ่งเหล่านี้
แฮ็คแฮ็ค!
this
จากis
นั้นtrue
แต่คุณจะเห็นค่าสุดท้ายที่ส่งคืนเท่านั้น (นี่คือและความจริงเป็นข้อความแยกต่างหาก)
มันบอกว่า "อย่าประเมินฉัน" ตัวอย่างเช่นหากคุณต้องการใช้รายการเป็นข้อมูลไม่ใช่เป็นรหัสคุณจะต้องใส่ใบเสนอราคาไว้ข้างหน้า ตัวอย่างเช่น,
(print '(+ 3 4))
พิมพ์ "(+ 3 4)" ในขณะที่
(print (+ 3 4))
พิมพ์ "7"
unquote
คำสั่ง?
eval
: (print (eval '(+ 3 4)))
. นี่คือสิ่งที่ทำให้ Lisps ยอดเยี่ยมมาก: รายการคือรหัสและรหัสคือรายการดังนั้นโปรแกรม Lisp สามารถจัดการตัวเองได้
คนอื่น ๆ ตอบคำถามนี้อย่างน่าชื่นชมและ Matthias Benkard ก็เตือนอย่างดี
อย่าใช้ใบเสนอราคาเพื่อสร้างรายการที่คุณจะแก้ไขในภายหลัง ข้อมูลจำเพาะช่วยให้คอมไพลเลอร์ถือว่ารายการที่ยกมาเป็นค่าคงที่ บ่อยครั้งคอมไพลเลอร์จะปรับค่าคงที่ให้เหมาะสมโดยการสร้างค่าเดียวสำหรับค่าเหล่านั้นในหน่วยความจำจากนั้นอ้างอิงค่าเดียวจากตำแหน่งทั้งหมดที่ค่าคงที่ปรากฏ กล่าวอีกนัยหนึ่งก็คืออาจถือว่าค่าคงที่เหมือนตัวแปรส่วนกลางที่ไม่ระบุตัวตน
ซึ่งอาจทำให้เกิดปัญหาที่ชัดเจน หากคุณแก้ไขค่าคงที่ค่าคงที่อาจปรับเปลี่ยนการใช้งานอื่น ๆ ของค่าคงที่เดียวกันในโค้ดที่ไม่เกี่ยวข้องได้อย่างสมบูรณ์ ตัวอย่างเช่นคุณอาจเปรียบเทียบตัวแปรบางตัวกับ '(1 1) ในบางฟังก์ชันและในฟังก์ชันที่แตกต่างกันโดยสิ้นเชิงให้เริ่มรายการด้วย' (1 1) จากนั้นเพิ่มข้อมูลเพิ่มเติมเข้าไป เมื่อเรียกใช้ฟังก์ชันเหล่านี้คุณอาจพบว่าฟังก์ชันแรกไม่ตรงกับสิ่งต่างๆอย่างถูกต้องอีกต่อไปเนื่องจากตอนนี้กำลังพยายามเปรียบเทียบตัวแปรกับ '(1 1 2 3 5 8 13) ซึ่งเป็นสิ่งที่ฟังก์ชันที่สองส่งคืน ฟังก์ชันทั้งสองนี้ไม่เกี่ยวข้องกันโดยสิ้นเชิง แต่มีผลกระทบซึ่งกันและกันเนื่องจากการใช้ค่าคงที่ แม้แต่เอฟเฟกต์ที่เลวร้ายกว่าก็สามารถเกิดขึ้นได้เช่นการวนซ้ำรายการปกติอย่างสมบูรณ์แบบจู่ๆก็วนซ้ำไม่สิ้นสุด
ใช้ใบเสนอราคาเมื่อคุณต้องการรายการคงที่เช่นเพื่อเปรียบเทียบ ใช้รายการเมื่อคุณจะแก้ไขผลลัพธ์
(list (+ 1 2))
เวลาส่วนใหญ่ ถ้าเป็นเช่นนั้นคุณจะป้องกันไม่ให้มีการประเมิน(+ 1 2)
ภายในตัวอย่างได้อย่างไร? มีunquote
คำสั่งหรือไม่?
'((3))
หรือเทียบเท่ากับ'((+ 1 2))
? ถ้าเป็นอย่างหลังคุณต้องใช้มากขึ้นlist
: (list (list '+ 1 2))
. หรือถ้าคุณต้องการเทียบเท่า'(+ 1 2)
ก็แค่(list '+ 1 2)
. และโปรดจำไว้ว่าหากคุณไม่ได้แก้ไขรายการโปรดอย่าลังเลที่จะใช้ quote: ไม่มีอะไรผิดปกติ'(+ 1 2)
หากคุณกำลังเปรียบเทียบกับรายการนี้หรือบางอย่าง
คำตอบหนึ่งสำหรับคำถามนี้กล่าวว่า QUOTE "สร้างโครงสร้างข้อมูลรายการ" นี่ไม่ถูกต้องนัก QUOTE เป็นพื้นฐานมากกว่านี้ ในความเป็นจริง QUOTE เป็นตัวดำเนินการที่ไม่สำคัญ: มีวัตถุประสงค์เพื่อป้องกันไม่ให้เกิดอะไรขึ้นเลย โดยเฉพาะอย่างยิ่งมันไม่ได้สร้างอะไร
สิ่งที่ (QUOTE X) พูดโดยพื้นฐานแล้วคือ“ อย่าทำอะไรเลยแค่ให้ X แก่ฉัน” X ไม่จำเป็นต้องเป็นรายการใน (QUOTE (ABC)) หรือสัญลักษณ์เหมือนใน (QUOTE FOO) อาจเป็นวัตถุอะไรก็ได้ อันที่จริงผลของการประเมินรายการที่สร้างขึ้นโดย (LIST 'QUOTE SOME-OBJECT) จะส่งคืนบางส่วนเสมอไม่ว่าจะเป็นอะไรก็ตาม
ตอนนี้เหตุผลที่ (QUOTE (ABC)) ดูเหมือนว่ามันสร้างรายการที่มีองค์ประกอบเป็น A, B และ C นั่นคือรายการดังกล่าวเป็นสิ่งที่ส่งคืนจริงๆ แต่ในขณะที่แบบฟอร์ม QUOTE ได้รับการประเมินโดยทั่วไปแล้วรายการจะมีอยู่มาระยะหนึ่งแล้ว (เป็นส่วนประกอบของแบบฟอร์ม QUOTE!) ซึ่งสร้างขึ้นโดยตัวโหลดหรือผู้อ่านก่อนที่จะเรียกใช้โค้ด
นัยหนึ่งของสิ่งนี้ที่มีแนวโน้มที่จะเดินทางไปหามือใหม่บ่อยครั้งก็คือการแก้ไขรายการที่ส่งคืนโดยรูปแบบ QUOTE นั้นไม่ฉลาด ข้อมูลที่ส่งคืนโดย QUOTE นั้นสำหรับเจตนาและวัตถุประสงค์ทั้งหมดจะถือว่าเป็นส่วนหนึ่งของโค้ดที่กำลังดำเนินการดังนั้นจึงควรถือว่าเป็นแบบอ่านอย่างเดียว!
ใบเสนอราคาป้องกันการดำเนินการหรือการประเมินฟอร์มโดยเปลี่ยนเป็นข้อมูลแทน โดยทั่วไปคุณสามารถดำเนินการกับข้อมูลโดยการประเมินแล้ว
quote สร้างโครงสร้างข้อมูลรายการตัวอย่างเช่นสิ่งต่อไปนี้เทียบเท่า:
(quote a)
'a
นอกจากนี้ยังสามารถใช้เพื่อสร้างรายการ (หรือต้นไม้):
(quote (1 2 3))
'(1 2 3)
คุณน่าจะดีที่สุดหากซื้อหนังสือเบื้องต้นเกี่ยวกับเสียงกระเพื่อมเช่นPractical Common Lisp (ซึ่งมีให้อ่านทางออนไลน์)
ใน Emacs Lisp:
สามารถอ้างอะไรได้บ้าง?
รายการและสัญลักษณ์
อ้างประเมินจำนวนไปยังหมายเลขที่ตัวเอง:
เป็นเช่นเดียวกับ'5
5
จะเกิดอะไรขึ้นเมื่อคุณอ้างรายการ
ตัวอย่างเช่น:
'(one two)
ประเมินเป็น
(list 'one 'two)
ซึ่งประเมินถึง
(list (intern "one") (intern ("two")))
.
(intern "one")
สร้างสัญลักษณ์ชื่อ "หนึ่ง" และเก็บไว้ในแฮชแมป "ส่วนกลาง" ดังนั้นเมื่อใดก็ตามที่คุณพูด'one
สัญลักษณ์ที่ชื่อ"one"
จะถูกค้นหาในแผนที่แฮชส่วนกลางนั้น
แต่สัญลักษณ์คืออะไร?
ตัวอย่างเช่นในภาษา OO (Java / Javascript / Python) สัญลักษณ์สามารถแสดงเป็นวัตถุที่มีname
เขตข้อมูลซึ่งเป็นชื่อของสัญลักษณ์เหมือน"one"
ด้านบนและข้อมูลและ / หรือรหัสสามารถเชื่อมโยงกับวัตถุนี้ได้
ดังนั้นสัญลักษณ์ใน Python สามารถใช้งานได้ดังนี้:
class Symbol:
def __init__(self,name,code,value):
self.name=name
self.code=code
self.value=value
ตัวอย่างเช่นใน Emacs Lisp สัญลักษณ์สามารถมี 1) ข้อมูลที่เชื่อมโยงกับมันและ (ในเวลาเดียวกัน - สำหรับสัญลักษณ์เดียวกัน) 2) รหัสที่เกี่ยวข้อง - ขึ้นอยู่กับบริบทข้อมูลหรือรหัสจะถูกเรียก
ตัวอย่างเช่นใน Elisp:
(progn
(fset 'add '+ )
(set 'add 2)
(add add add)
)
4
ประเมิน
เนื่องจาก(add add add)
ประเมินเป็น:
(add add add)
(+ add add)
(+ 2 add)
(+ 2 2)
4
ตัวอย่างเช่นการใช้Symbol
คลาสที่เรากำหนดไว้ใน Python ด้านบนadd
ELisp-Symbol นี้สามารถเขียนใน Python เป็นSymbol("add",(lambda x,y: x+y),2)
.
ขอบคุณมากสำหรับผู้ใช้ IRC #emac สำหรับการอธิบายสัญลักษณ์และคำพูดให้ฉัน
เมื่อเราต้องการส่งผ่านอาร์กิวเมนต์แทนการส่งผ่านค่าของอาร์กิวเมนต์เราจะใช้เครื่องหมายคำพูด ส่วนใหญ่เกี่ยวข้องกับขั้นตอนการส่งผ่านระหว่างการใช้รายการคู่และอะตอมซึ่งไม่มีในภาษาโปรแกรม C (คนส่วนใหญ่เริ่มเขียนโปรแกรมโดยใช้โปรแกรม C ดังนั้นเราจึงสับสน) นี่คือรหัสในภาษาโปรแกรม Scheme ซึ่งเป็นภาษาถิ่นของเสียงกระเพื่อม และฉันเดาว่าคุณเข้าใจรหัสนี้
(define atom? ; defining a procedure atom?
(lambda (x) ; which as one argument x
(and (not (null? x)) (not(pair? x) )))) ; checks if the argument is atom or not
(atom? '(a b c)) ; since it is a list it is false #f
บรรทัดสุดท้าย (atom? 'abc) กำลังผ่าน abc ตามที่เป็นขั้นตอนเพื่อตรวจสอบว่า abc เป็นอะตอมหรือไม่ แต่เมื่อคุณผ่าน (atom? abc) มันจะตรวจสอบค่าของ abc และส่งผ่านค่าไปยัง มัน. เนื่องจากเราไม่ได้ให้คุณค่าใด ๆ กับมัน
Code is data and data is code. There is no clear distinction between them.
นี่เป็นคำพูดคลาสสิกที่โปรแกรมเมอร์เสียงกระเพื่อมทุกคนรู้
เมื่อคุณอ้างรหัสรหัสนั้นจะเป็นข้อมูล
1 ]=> '(+ 2 3 4)
;Value: (+ 2 3 4)
1 ]=> (+ 2 3 4)
;Value: 9
เมื่อคุณอ้างรหัสผลลัพธ์จะเป็นข้อมูลที่แสดงรหัสนั้น ดังนั้นเมื่อคุณต้องการทำงานกับข้อมูลที่แสดงถึงโปรแกรมที่คุณอ้างถึงโปรแกรมนั้น นอกจากนี้ยังใช้ได้กับนิพจน์อะตอมไม่เพียง แต่สำหรับรายการ:
1 ]=> 'code
;Value: code
1 ]=> '10
;Value: 10
1 ]=> '"ok"
;Value: "ok"
1 ]=> code
;Unbound variable: code
สมมติว่าคุณต้องการสร้างภาษาโปรแกรมที่ฝังอยู่ในเสียงกระเพื่อม - คุณจะทำงานกับโปรแกรมที่ยกมาในรูปแบบ (เหมือน'(+ 2 3)
) และถูกตีความว่าเป็นรหัสในภาษาที่คุณสร้างขึ้นโดยให้โปรแกรมตีความหมาย ในกรณีนี้คุณต้องใช้ใบเสนอราคาเพื่อเก็บข้อมูลมิฉะนั้นจะได้รับการประเมินเป็นภาษาภายนอก
ใบเสนอราคาส่งกลับการแทนค่าภายในของอาร์กิวเมนต์ หลังจากไถคำอธิบายมากเกินไปเกี่ยวกับสิ่งที่อ้างไม่ได้นั่นคือตอนที่หลอดไฟเดินต่อไป หาก REPL ไม่ได้แปลงชื่อฟังก์ชั่นเป็น UPPER-CASE เมื่อฉันยกมามันอาจจะไม่เกิดขึ้นกับฉัน
ดังนั้น. ฟังก์ชัน Lisp สามัญแปลงอาร์กิวเมนต์เป็นการแสดงภายในประเมินอาร์กิวเมนต์และใช้ฟังก์ชัน Quote แปลงอาร์กิวเมนต์เป็นการแสดงภายในและส่งกลับค่านั้น ในทางเทคนิคถูกต้องที่จะพูดว่าคำพูดที่ว่า "อย่าประเมิน" แต่เมื่อฉันพยายามทำความเข้าใจว่ามันทำอะไรการบอกว่าสิ่งที่ไม่ได้ทำนั้นทำให้ฉันหงุดหงิด เครื่องปิ้งขนมปังของฉันไม่ได้ประเมินฟังก์ชัน Lisp เช่นกัน แต่นั่นไม่ใช่วิธีที่คุณอธิบายว่าเครื่องปิ้งขนมปังทำอะไร
คำตอบสั้น ๆ ของ Anoter:
quote
วิธีการประเมินโดยไม่มันและbackquoteคืออ้าง แต่ปล่อยให้ประตูหลัง
การอ้างอิงที่ดี:
คู่มืออ้างอิง Emacs Lisp ทำให้ชัดเจนมาก
9.3 การอ้างอิง
ใบเสนอราคารูปแบบพิเศษส่งคืนอาร์กิวเมนต์เดียวตามที่เขียนไว้โดยไม่ต้องประเมิน นี่เป็นวิธีการรวมสัญลักษณ์และรายการคงที่ซึ่งไม่ใช่ออบเจ็กต์ประเมินตนเองในโปรแกรม (ไม่จำเป็นต้องอ้างอิงวัตถุที่ประเมินตนเองเช่นตัวเลขสตริงและเวกเตอร์)
แบบฟอร์มพิเศษ: อ้างวัตถุ
This special form returns object, without evaluating it.
เนื่องจากมีการใช้เครื่องหมายคำพูดบ่อยครั้งในโปรแกรม Lisp จึงมีไวยากรณ์การอ่านที่สะดวกสำหรับมัน อักขระเครื่องหมายวรรคตอน ('' ') ตามด้วยวัตถุ Lisp (ในรูปแบบการอ่าน) จะขยายไปยังรายการที่มีองค์ประกอบแรกเป็นเครื่องหมายคำพูดและองค์ประกอบที่สองคือวัตถุ ดังนั้นไวยากรณ์การอ่าน 'x จึงเป็นคำย่อของ (quote x)
นี่คือตัวอย่างบางส่วนของนิพจน์ที่ใช้ quote:
(quote (+ 1 2))
⇒ (+ 1 2)
(quote foo)
⇒ foo
'foo
⇒ foo
''foo
⇒ (quote foo)
'(quote foo)
⇒ (quote foo)
9.4 Backquote
โครงสร้าง Backquote ช่วยให้คุณสามารถอ้างอิงรายการ แต่เลือกประเมินองค์ประกอบของรายการนั้น ในกรณีที่ง่ายที่สุดจะเหมือนกับใบเสนอราคารูปแบบพิเศษ (อธิบายไว้ในส่วนก่อนหน้าดูการอ้างอิง) ตัวอย่างเช่นสองรูปแบบนี้ให้ผลลัพธ์ที่เหมือนกัน:
`(a list of (+ 2 3) elements)
⇒ (a list of (+ 2 3) elements)
'(a list of (+ 2 3) elements)
⇒ (a list of (+ 2 3) elements)
เครื่องหมายพิเศษ ',' ภายในอาร์กิวเมนต์เพื่อ backquote ระบุค่าที่ไม่คงที่ ผู้ประเมิน Emacs Lisp ประเมินอาร์กิวเมนต์ของ ',' และใส่ค่าในโครงสร้างรายการ:
`(a list of ,(+ 2 3) elements)
⇒ (a list of 5 elements)
การแทนที่ด้วย "," จะได้รับอนุญาตในระดับลึกของโครงสร้างรายการด้วย ตัวอย่างเช่น:
`(1 2 (3 ,(+ 4 5)))
⇒ (1 2 (3 9))
คุณยังสามารถแบ่งค่าที่ประเมินลงในรายการผลลัพธ์โดยใช้เครื่องหมายพิเศษ ', @' องค์ประกอบของรายการที่ต่อกันกลายเป็นองค์ประกอบในระดับเดียวกับองค์ประกอบอื่น ๆ ของรายการผลลัพธ์ รหัสที่เทียบเท่าโดยไม่ใช้ '' 'มักจะไม่สามารถอ่านได้ นี่คือตัวอย่างบางส่วน:
(setq some-list '(2 3))
⇒ (2 3)
(cons 1 (append some-list '(4) some-list))
⇒ (1 2 3 4 2 3)
`(1 ,@some-list 4 ,@some-list)
⇒ (1 2 3 4 2 3)