4

我很难理解宏扩展是如何工作的。elisp 解释器处理这两个代码片段的方式有什么区别?

(defmacro foo (arg)
  (message "arg is: %s" arg))
(foo "bar")

和:

(defmacro foo (arg)
  `(message "arg is: %s" ,arg))
(foo "bar")
4

1 回答 1

8

您的示例可能会令人困惑,因为

  1. message两者都显示一条消息并返回它。
  2. 字符串(如“bar”)是自我评估的。

有指导意义的例子

(defconst zzz 123)
(defmacro zzz1 (arg)
  `(insert (format "arg is: %s" ,arg)))
(defmacro zzz2 (arg)
  (insert (format "arg is: %s" arg)))

C-x C-e在 3 种形式之后使用上面的代码来评估。

现在评估这些:

第一个版本:(zzz1 zzz)

口译员...

  1. 调用宏函数zzz1
  2. 宏函数返回表单(insert (format "arg is: %s" zzz))
  3. 解释器评估表单,插入"arg is: 123"当前缓冲区,然后返回nil(在底部的回显区域中看到)

第二个版本:(zzz2 zzz)

口译员...

  1. 调用宏函数zzz2
  2. 宏函数插入"arg is: zzz"当前缓冲区并返回nil
  3. 解释器评估nilnil(在回声中看到在底部)

底线

这里最重要的“要点”是宏只是在解释器(编译器)启动之前对代码进行操作的函数。

这些函数对它们的参数进行不求值(即,在zzz1and zzz2argiszzz和 not中123)。

它们像任何其他 lisp 函数一样被评估(例如,它们的主体中可以有宏形式;主体被包裹在一个隐含的progn; &c 中)。

它们的返回值由解释器评估,而不是原始形式。

于 2013-06-13T17:36:28.707 回答