为什么对下列内容进行字节编译会产生警告?
(defmacro foomacro (shiftcode)
`(defun foo (&optional arg)
(interactive ,(concat shiftcode "p"))
(message "arg is %i" arg))
`(defun bar (&optional arg)
(interactive ,(concat shiftcode "Nenter a number: "))
(message "arg is %i" arg)))
;; provide backward compatibility for Emacs 22
(if (fboundp 'handle-shift-selection)
(foomacro "^")
(foomacro ""))
这是我得到的警告:
$ emacs -Q --batch --eval '(byte-compile-file "foo.el")'
In foomacro:
foo.el:1:21:Warning: value returned from (concat shiftcode "p") is unused
如果去掉bar
,警告就消失了:
(defmacro foomacro (shiftcode)
`(defun foo (&optional arg)
(interactive ,(concat shiftcode "p"))
(message "arg is %i" arg)))
;; provide backward compatibility for Emacs 22
(if (fboundp 'handle-shift-selection)
(foomacro "^")
(foomacro ""))
这是因为您忘记在程序中包装宏体:
(defmacro foomacro (shiftcode)
`(progn
(defun foo (&optional arg)
(interactive ,(concat shiftcode "p"))
(message "arg is %i" arg))
(defun bar (&optional arg)
(interactive ,(concat shiftcode "Nenter a number: "))
(message "arg is %i" arg))))
想想宏是如何工作的。当您调用(foomacro "...")
时,lisp引擎识别出foomacro
是一个宏,并将展开,即根据提供的参数调用它。宏的返回值如预期的为第二个 defun
形式;而第一个 defun
形式被丢弃。然后lisp引擎计算返回值(即第二个 defun
形式)。因此,在没有progn
的版本中,只定义了bar
,而没有定义foo
。
要理解这个过程,你需要意识到宏仅仅是"代码转换"工具;他们什么都不做。因此,编译器(或解释器)只能看到它们的返回值。