ประเมิน docstring ในมาโคร

Sep 27 2020

มาโครเช่นdefun(หรือdefmacroตัวมันเอง) มีdocstringอาร์กิวเมนต์ที่เป็นทางเลือกแต่เนื่องจากเป็นมาโครไม่ใช่ฟังก์ชันdocstringจึงไม่ได้รับการประเมิน แต่ถูกนำมาใช้ตามที่เป็นอยู่

ฉันต้องการที่docstringจะได้รับการประเมินดังนั้นแทนที่จะเป็นแบบนี้ -

"does a, then b, then c" ; b is hardcoded

ฉันใส่อะไรแบบนี้แทนได้ -

(concat "does a, then " (getenv "<some-shell-variable>") " , then c") ; b isn't hardcoded

เป็นไปได้หรือไม่ที่จะทำเช่นนี้โดยไม่ต้องปรับเปลี่ยนคำจำกัดความของdefunและdefmacro?

โดยปรับแต่งผมไม่ได้หมายถึงการเขียนทับคำจำกัดความ แต่เขียนแมโครใหม่เช่นprefix-defunและprefix-defmacroอยู่บนพื้นฐานของคำจำกัดความที่มีอยู่ของdefunและdemacroยกเว้น docstring จะถูกประเมินโดยการเปลี่ยนทุกกรณีด้วยdocstring(eval docstring)

คำตอบ

1 Drew Sep 28 2020 at 03:33

คุณสามารถตั้งค่าสตริง doc ของฟังก์ชันตัวแปรหรือหันหน้าไปยังสตริงใดก็ได้ที่คุณต้องการไม่ว่าจะ (สร้างแบบไดนามิกหรือไม่ก็ตาม)

สำหรับฟังก์ชันfooให้ใส่สตริงที่คุณต้องการบนสัญลักษณ์fooเป็นค่าคุณสมบัติfunction-documentation:

(defun foo () ; `foo' gets no doc string from this defun.
  (interactive)
  (message "FOOOOOOOO"))

(put 'foo 'function-documentation "I'm `foo'.") ; Give function `foo' a doc string.
(put 'foo 'function-documentation "I'm NEW `foo' doc.") ; Redefine the doc string.

สิ่งเดียวกันสำหรับ defvar หรือ defcustom - ใช้คุณสมบัติสัญลักษณ์variable-documentation:

(defvar foo 42) ; Variable `foo' has no doc string.

(put 'foo 'variable-documentation "I'm `foo'.") ; Give var `foo' a doc string.
(put 'foo 'variable-documentation "I'm NEW `foo' .") ; Redefine the doc string.

ดูคู่มือ Elisp ข้อมูลพื้นฐานเกี่ยวกับโหนดและโหนดย่อย

สิ่งเดียวกันสำหรับdefface- variable-documentationใช้คุณสมบัติสัญลักษณ์ แต่deffaceต้องใช้สตริงเอกสาร อย่างไรก็ตามคุณสามารถเปลี่ยนแปลงแบบไดนามิกได้ตามที่คุณสามารถทำได้สำหรับฟังก์ชันหรือตัวแปร

(defface foo '((t :foreground "Red")) "0000") ; Doc string "0000".

(put 'foo 'face-documentation "11111") ; Change doc string to "1111".
2 phils Sep 27 2020 at 19:47
(defun foo ()
  (:documentation (concat "does a, then " (getenv "<some-shell-variable>") " , then c"))
  ...BODY...)

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

หากคุณต้องการ docstring ที่จะeval'd ตามความต้องการ (เช่นเวลาที่คุณขอมันทุก) คุณสามารถทำเช่นนั้นเช่นกัน :documentationแต่เห็นได้ชัดว่าไม่ได้อยู่กับ อ้างถึงคำตอบของฉันสำหรับคำถามก่อนหน้านี้สำหรับตัวเลือกบางอย่างในการทำเช่นนั้น