เมื่อใดควรใช้ '(หรือ quote) ใน Lisp?


114

หลังจากผ่านส่วนสำคัญของหนังสือ Lisp เบื้องต้นแล้วฉันยังไม่เข้าใจว่าฟังก์ชันตัวดำเนินการพิเศษ(quote)(หรือเทียบเท่า') ทำหน้าที่อะไร แต่นี่เป็นรหัส Lisp ทั้งหมดที่ฉันเคยเห็น

มันทำอะไร?

คำตอบ:


178

คำตอบสั้น ๆ ข้ามกฎการประเมินเริ่มต้นและไม่ประเมินนิพจน์ (สัญลักษณ์หรือ 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จะให้คำอธิบายที่ดีเกี่ยวกับสิ่งเหล่านี้

แฮ็คแฮ็ค!


ใน emacs SBCL ของฉันถูกตั้งค่าและเมื่อฉันพิมพ์ 'this' is 'true' มันจะส่งคืนค่าสุดท้ายคือ TRUE ในเอาต์พุตเท่านั้น แม้จะอยู่ในท่าเทียบเรือฉันก็ยังได้ผลผลิตเหมือนกัน
Totoro

@Totoro ค่าที่ส่งคืนของฟังก์ชันหรือคำสั่งหลาย ๆ คำในเสียงกระเพื่อมคือนิพจน์สุดท้ายดังนั้นจึงส่งคืนจริงthisจากisนั้นtrueแต่คุณจะเห็นค่าสุดท้ายที่ส่งคืนเท่านั้น (นี่คือและความจริงเป็นข้อความแยกต่างหาก)
Wezl

52

มันบอกว่า "อย่าประเมินฉัน" ตัวอย่างเช่นหากคุณต้องการใช้รายการเป็นข้อมูลไม่ใช่เป็นรหัสคุณจะต้องใส่ใบเสนอราคาไว้ข้างหน้า ตัวอย่างเช่น,

(print '(+ 3 4))พิมพ์ "(+ 3 4)" ในขณะที่ (print (+ 3 4))พิมพ์ "7"


จะประเมินอย่างไรแล้วเช่นมีunquoteคำสั่ง?
Lime

3
@ William Lisps มีฟังก์ชั่นอำนวยความสะดวกที่เรียกว่าeval: (print (eval '(+ 3 4))). นี่คือสิ่งที่ทำให้ Lisps ยอดเยี่ยมมาก: รายการคือรหัสและรหัสคือรายการดังนั้นโปรแกรม Lisp สามารถจัดการตัวเองได้
darkfeline

18

คนอื่น ๆ ตอบคำถามนี้อย่างน่าชื่นชมและ Matthias Benkard ก็เตือนอย่างดี

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

ซึ่งอาจทำให้เกิดปัญหาที่ชัดเจน หากคุณแก้ไขค่าคงที่ค่าคงที่อาจปรับเปลี่ยนการใช้งานอื่น ๆ ของค่าคงที่เดียวกันในโค้ดที่ไม่เกี่ยวข้องได้อย่างสมบูรณ์ ตัวอย่างเช่นคุณอาจเปรียบเทียบตัวแปรบางตัวกับ '(1 1) ในบางฟังก์ชันและในฟังก์ชันที่แตกต่างกันโดยสิ้นเชิงให้เริ่มรายการด้วย' (1 1) จากนั้นเพิ่มข้อมูลเพิ่มเติมเข้าไป เมื่อเรียกใช้ฟังก์ชันเหล่านี้คุณอาจพบว่าฟังก์ชันแรกไม่ตรงกับสิ่งต่างๆอย่างถูกต้องอีกต่อไปเนื่องจากตอนนี้กำลังพยายามเปรียบเทียบตัวแปรกับ '(1 1 2 3 5 8 13) ซึ่งเป็นสิ่งที่ฟังก์ชันที่สองส่งคืน ฟังก์ชันทั้งสองนี้ไม่เกี่ยวข้องกันโดยสิ้นเชิง แต่มีผลกระทบซึ่งกันและกันเนื่องจากการใช้ค่าคงที่ แม้แต่เอฟเฟกต์ที่เลวร้ายกว่าก็สามารถเกิดขึ้นได้เช่นการวนซ้ำรายการปกติอย่างสมบูรณ์แบบจู่ๆก็วนซ้ำไม่สิ้นสุด

ใช้ใบเสนอราคาเมื่อคุณต้องการรายการคงที่เช่นเพื่อเปรียบเทียบ ใช้รายการเมื่อคุณจะแก้ไขผลลัพธ์


ดูเหมือนว่าคุณควรใช้(list (+ 1 2)) เวลาส่วนใหญ่ ถ้าเป็นเช่นนั้นคุณจะป้องกันไม่ให้มีการประเมิน(+ 1 2)ภายในตัวอย่างได้อย่างไร? มีunquoteคำสั่งหรือไม่?
Lime

1
คุณต้องการเทียบเท่า'((3))หรือเทียบเท่ากับ'((+ 1 2))? ถ้าเป็นอย่างหลังคุณต้องใช้มากขึ้นlist: (list (list '+ 1 2)). หรือถ้าคุณต้องการเทียบเท่า'(+ 1 2)ก็แค่(list '+ 1 2). และโปรดจำไว้ว่าหากคุณไม่ได้แก้ไขรายการโปรดอย่าลังเลที่จะใช้ quote: ไม่มีอะไรผิดปกติ'(+ 1 2)หากคุณกำลังเปรียบเทียบกับรายการนี้หรือบางอย่าง
Xanthir

1
คุณคิดว่าการอ้างอิงว่ารายการที่ยกมาควรถือว่าเป็นค่าคงที่หรือไม่?
Lime

HyperSpec clhs.lisp.se/Body/s_quote.htmกล่าวว่าพฤติกรรมไม่ได้รับการกำหนดหากวัตถุที่ยกมาถูกแก้ไขอย่างทำลาย โดยนัยว่านี่เป็นการอนุญาตโดยนัยให้ถือว่าค่าเป็นค่าอะตอม
Xanthir

14

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

สิ่งที่ (QUOTE X) พูดโดยพื้นฐานแล้วคือ“ อย่าทำอะไรเลยแค่ให้ X แก่ฉัน” X ไม่จำเป็นต้องเป็นรายการใน (QUOTE (ABC)) หรือสัญลักษณ์เหมือนใน (QUOTE FOO) อาจเป็นวัตถุอะไรก็ได้ อันที่จริงผลของการประเมินรายการที่สร้างขึ้นโดย (LIST 'QUOTE SOME-OBJECT) จะส่งคืนบางส่วนเสมอไม่ว่าจะเป็นอะไรก็ตาม

ตอนนี้เหตุผลที่ (QUOTE (ABC)) ดูเหมือนว่ามันสร้างรายการที่มีองค์ประกอบเป็น A, B และ C นั่นคือรายการดังกล่าวเป็นสิ่งที่ส่งคืนจริงๆ แต่ในขณะที่แบบฟอร์ม QUOTE ได้รับการประเมินโดยทั่วไปแล้วรายการจะมีอยู่มาระยะหนึ่งแล้ว (เป็นส่วนประกอบของแบบฟอร์ม QUOTE!) ซึ่งสร้างขึ้นโดยตัวโหลดหรือผู้อ่านก่อนที่จะเรียกใช้โค้ด

นัยหนึ่งของสิ่งนี้ที่มีแนวโน้มที่จะเดินทางไปหามือใหม่บ่อยครั้งก็คือการแก้ไขรายการที่ส่งคืนโดยรูปแบบ QUOTE นั้นไม่ฉลาด ข้อมูลที่ส่งคืนโดย QUOTE นั้นสำหรับเจตนาและวัตถุประสงค์ทั้งหมดจะถือว่าเป็นส่วนหนึ่งของโค้ดที่กำลังดำเนินการดังนั้นจึงควรถือว่าเป็นแบบอ่านอย่างเดียว!


11

ใบเสนอราคาป้องกันการดำเนินการหรือการประเมินฟอร์มโดยเปลี่ยนเป็นข้อมูลแทน โดยทั่วไปคุณสามารถดำเนินการกับข้อมูลโดยการประเมินแล้ว

quote สร้างโครงสร้างข้อมูลรายการตัวอย่างเช่นสิ่งต่อไปนี้เทียบเท่า:

(quote a)
'a

นอกจากนี้ยังสามารถใช้เพื่อสร้างรายการ (หรือต้นไม้):

(quote (1 2 3))
'(1 2 3)

คุณน่าจะดีที่สุดหากซื้อหนังสือเบื้องต้นเกี่ยวกับเสียงกระเพื่อมเช่นPractical Common Lisp (ซึ่งมีให้อ่านทางออนไลน์)


3

ใน Emacs Lisp:

สามารถอ้างอะไรได้บ้าง?

รายการและสัญลักษณ์

อ้างประเมินจำนวนไปยังหมายเลขที่ตัวเอง: เป็นเช่นเดียวกับ'55

จะเกิดอะไรขึ้นเมื่อคุณอ้างรายการ

ตัวอย่างเช่น:

'(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 ด้านบนaddELisp-Symbol นี้สามารถเขียนใน Python เป็นSymbol("add",(lambda x,y: x+y),2).

ขอบคุณมากสำหรับผู้ใช้ IRC #emac สำหรับการอธิบายสัญลักษณ์และคำพูดให้ฉัน


2

เมื่อเราต้องการส่งผ่านอาร์กิวเมนต์แทนการส่งผ่านค่าของอาร์กิวเมนต์เราจะใช้เครื่องหมายคำพูด ส่วนใหญ่เกี่ยวข้องกับขั้นตอนการส่งผ่านระหว่างการใช้รายการคู่และอะตอมซึ่งไม่มีในภาษาโปรแกรม 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 และส่งผ่านค่าไปยัง มัน. เนื่องจากเราไม่ได้ให้คุณค่าใด ๆ กับมัน


2
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)) และถูกตีความว่าเป็นรหัสในภาษาที่คุณสร้างขึ้นโดยให้โปรแกรมตีความหมาย ในกรณีนี้คุณต้องใช้ใบเสนอราคาเพื่อเก็บข้อมูลมิฉะนั้นจะได้รับการประเมินเป็นภาษาภายนอก


1

ใบเสนอราคาส่งกลับการแทนค่าภายในของอาร์กิวเมนต์ หลังจากไถคำอธิบายมากเกินไปเกี่ยวกับสิ่งที่อ้างไม่ได้นั่นคือตอนที่หลอดไฟเดินต่อไป หาก REPL ไม่ได้แปลงชื่อฟังก์ชั่นเป็น UPPER-CASE เมื่อฉันยกมามันอาจจะไม่เกิดขึ้นกับฉัน

ดังนั้น. ฟังก์ชัน Lisp สามัญแปลงอาร์กิวเมนต์เป็นการแสดงภายในประเมินอาร์กิวเมนต์และใช้ฟังก์ชัน Quote แปลงอาร์กิวเมนต์เป็นการแสดงภายในและส่งกลับค่านั้น ในทางเทคนิคถูกต้องที่จะพูดว่าคำพูดที่ว่า "อย่าประเมิน" แต่เมื่อฉันพยายามทำความเข้าใจว่ามันทำอะไรการบอกว่าสิ่งที่ไม่ได้ทำนั้นทำให้ฉันหงุดหงิด เครื่องปิ้งขนมปังของฉันไม่ได้ประเมินฟังก์ชัน Lisp เช่นกัน แต่นั่นไม่ใช่วิธีที่คุณอธิบายว่าเครื่องปิ้งขนมปังทำอะไร


1

คำตอบสั้น ๆ ของ 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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.