宏观扩张:引用身体形式与否?

Ric*_*sen 3 emacs elisp emacs24

我很难理解宏扩展是如何工作的.elisp解释器如何处理这两段代码有什么不同?

(defmacro foo (arg)
  (message "arg is: %s" arg))
(foo "bar")
Run Code Online (Sandbox Code Playgroud)

和:

(defmacro foo (arg)
  `(message "arg is: %s" ,arg))
(foo "bar")
Run Code Online (Sandbox Code Playgroud)

sds*_*sds 7

你的例子可能令人困惑,因为

  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)))
Run Code Online (Sandbox Code Playgroud)

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(在回声中看到底部)

底线

这里最重要的"外卖"是宏只是在解释器(编译器)启动之前对代码进行操作的函数.

这些函数及其参数未计算(即,在这两个zzz1zzz2,argzzz,不是123).

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

它们的返回值由解释器而不是原始形式进行评估.