gpt4 book ai didi

emacs - elisp宏扩展局部变量

转载 作者:太空宇宙 更新时间:2023-11-03 18:46:06 25 4
gpt4 key购买 nike

我最近接触了 elisp,并试图了解 elisp 宏的工作原理。GNU 教程有一个 chapter Surprising-local-Vars对于宏局部变量,我对宏扩展的工作原理感到困惑。

(defmacro for (var from init to final do &rest body)
"Execute a simple for loop: (for i from 1 to 10 do (print i))."
(let ((tempvar (make-symbol "max")))
`(let ((,var ,init)
(,tempvar ,final))
(while (<= ,var ,tempvar)
,@body
(inc ,var)))))

有两种 let 形式。第一个

(let ((tempvar (make-symbol "max")))

没有反引号,它将在宏扩展短语处进行评估,因此未插入的符号“max”将仅在该短语处创建。并且 uninterned 符号“max”会在运行时丢失,它应该不能正常工作吧?

但实际上,它运作良好。我尝试了以下方法:

(for max from 1 to 10 do (print max))

及其扩展如下:

(macroexpand '(for max from 1 to 10 do (print max)))

(let ((max 1) (max 10)) (while (<= max max) (print max) (setq max (+ 1 max))))

这里有两个max符号,一个绑定(bind)1,一个绑定(bind)10,while形式的表达式有两个max符号。

(while (<= max max)

while形式如何解析两个不同的符号“max”?

最佳答案

您正在查看打印名称,而不是符号标识。您有两个符号,都具有“打印名称”max,但身份不同。通常,我会推荐使用 gensym 而不是 make-symbol,但使用哪种方式并不重要。

将符号视为指向一个小结构的指针,其中存储了各种值。其中之一是“名字”,当一个符号被驻留时,它被放置在一个特殊的结构中,所以你可以通过它的名字找到这个符号。您看到的是一个名为 max 的 interned 符号和一个名为 max 的 un-interned 符号。它们是不同的符号(也就是说,两个结构和指针因此不同),但是当您只看打印表示时,这并不明显。

快速演示,刚从 emacs“scratch”缓冲区中取出:

(defmacro demo (sym)
(let ((tmp (make-symbol "max")))
`(progn
(message "%s" (list ',tmp ',sym))
(eql ',tmp ',sym))))

demo

(macroexpand '(demo max))
(progn (message "%s" (list (quote max) (quote max))) (eql (quote max) (quote max)))

(demo max)
nil

如果您粘贴宏展开产生的文本并对它求值,您会看到您得到的是 t 而不是 nil,因为在读取表达式,你最终会得到相同的符号。

关于emacs - elisp宏扩展局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38268431/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com