มัณฑนากรนั้นเป็นเพียงฟังก์ชั่น
ตัวอย่างใน Common LISP:
(defun attributes (keywords function)
(loop for (key value) in keywords
do (setf (get function key) value))
function)
ในฟังก์ชั่นดังกล่าวข้างต้นเป็นสัญลักษณ์ (ซึ่งจะถูกส่งกลับโดยDEFUN
) และเราใส่แอตทริบิวต์ที่สัญลักษณ์ของรายการทรัพย์สิน
ตอนนี้เราสามารถเขียนมันรอบ ๆ นิยามฟังก์ชัน:
(attributes
'((version-added "2.2")
(author "Rainer Joswig"))
(defun foo (a b)
(+ a b))
)
ถ้าเราต้องการที่จะเพิ่มไวยากรณ์แฟนซีเช่นในหลามเราเขียนแมโครอ่าน มาโครผู้อ่านช่วยให้เราสามารถเขียนโปรแกรมในระดับของไวยากรณ์ s-expression:
(set-macro-character
#\@
(lambda (stream char)
(let ((decorator (read stream))
(arg (read stream))
(form (read stream)))
`(,decorator ,arg ,form))))
จากนั้นเราสามารถเขียน:
@attributes'((version-added "2.2")
(author "Rainer Joswig"))
(defun foo (a b)
(+ a b))
ผู้อ่านเสียงกระเพื่อมอ่านข้างต้นเพื่อ:
(ATTRIBUTES (QUOTE ((VERSION-ADDED "2.2")
(AUTHOR "Rainer Joswig")))
(DEFUN FOO (A B) (+ A B)))
ตอนนี้เรามีรูปแบบของการตกแต่งใน Common LISP
การรวมมาโครและมาโครเครื่องอ่าน
จริง ๆ แล้วฉันจะทำข้างต้นการแปลในรหัสจริงโดยใช้แมโครไม่ใช่ฟังก์ชั่น
(defmacro defdecorator (decorator arg form)
`(progn
,form
(,decorator ,arg ',(second form))))
(set-macro-character
#\@
(lambda (stream char)
(declare (ignore char))
(let* ((decorator (read stream))
(arg (read stream))
(form (read stream)))
`(defdecorator ,decorator ,arg ,form))))
การใช้งานดังกล่าวข้างต้นกับแมโครตัวอ่านเดียวกัน ข้อดีคือเรียบเรียงเสียงกระเพื่อมยังคงเห็นว่ามันเป็นสิ่งที่เรียกว่ารูปแบบระดับบนสุด - * การรูปแบบไฟล์คอมไพเลอร์ถือว่าระดับบนสุดพิเศษเช่นจะเพิ่มข้อมูลเกี่ยวกับพวกเขาเข้าไปรวบรวมเวลาที่สภาพแวดล้อม ในตัวอย่างข้างต้นเราจะเห็นว่ามาโครมองเข้าไปในซอร์สโค้ดและแยกชื่อ
ตัวอ่านเสียงกระเพื่อมอ่านตัวอย่างข้างต้นเป็น:
(DEFDECORATOR ATTRIBUTES
(QUOTE ((VERSION-ADDED "2.2")
(AUTHOR "Rainer Joswig")))
(DEFUN FOO (A B) (+ A B)))
ซึ่งได้รับมาโครขยายเป็น:
(PROGN (DEFUN FOO (A B) (+ A B))
(ATTRIBUTES (QUOTE ((VERSION-ADDED "2.2")
(AUTHOR "Rainer Joswig")))
(QUOTE FOO)))
แมโครมีความแตกต่างจากแมโครอ่าน
แมโครรับซอร์สโค้ดผ่านสามารถทำสิ่งที่ต้องการแล้วส่งคืนซอร์สโค้ด แหล่งอินพุตไม่จำเป็นต้องเป็นรหัส Lisp ที่ถูกต้อง มันสามารถเป็นอะไรก็ได้และมันสามารถเขียนต่างกันโดยสิ้นเชิง ผลลัพธ์จะต้องเป็นรหัส Lisp ที่ถูกต้องแล้ว แต่ถ้ารหัสที่สร้างขึ้นกำลังใช้แมโครด้วยเช่นกันไวยากรณ์ของรหัสที่ฝังในการเรียกแมโครอาจเป็นไวยากรณ์ที่แตกต่างกันอีกครั้ง ตัวอย่างง่ายๆ: หนึ่งสามารถเขียนแมโครคณิตศาสตร์ซึ่งจะยอมรับไวยากรณ์ทางคณิตศาสตร์บางชนิด:
(math y = 3 x ^ 2 - 4 x + 3)
การแสดงออกy = 3 x ^ 2 - 4 x + 3
ไม่ถูกต้องรหัส LISP แต่แมโครสามารถแยกวิเคราะห์ได้และส่งกลับรหัส LISP ที่ถูกต้องเช่นนี้
(setq y (+ (* 3 (expt x 2))
(- (* 4 x))
3))
มีกรณีการใช้งานอื่น ๆ ของมาโครใน Lisp