编写宏时最常见的问题,就是过早执行了实际工作 — 在宏展开阶段就执行,而不是把执行逻辑放在展开后的代码里。例如,某个实际的软件包曾有这样一个错误的宏定义:
(defmacro my-set-buffer-multibyte (arg)
(if (fboundp 'set-buffer-multibyte)
(set-buffer-multibyte arg)))
使用这个错误的宏定义,程序在解释执行时正常,但编译后就会出错。原因是:这个宏会在编译期间调用 set-buffer-multibyte,这是错误的;而编译后的程序在运行时,这段代码却什么都不做。
程序员真正想要的定义应该是这样:
(defmacro my-set-buffer-multibyte (arg)
(if (fboundp 'set-buffer-multibyte)
`(set-buffer-multibyte ,arg)))
在条件满足时,这个宏会展开成对 set-buffer-multibyte 的调用,而这个调用会在编译后的程序实际运行时才执行。