如果我在foo.el
中添加以下内容:
(defun whitespace-redraw ()
(eval-when-compile (require 'whitespace nil t))
(when (require 'whitespace nil t)
(if whitespace-mode
(whitespace-mode 0))
(whitespace-mode 1)))
然后字节编译它:
emacs -Q --batch --eval '(byte-compile-file "foo.el")'
我收到以下警告:
In end of data:
foo.el:7:1:Warning: the function `whitespace-mode' might not be defined at
runtime.
Wrote foo.elc
当然whitespace-mode
在运行时可以是未定义的,但除非成功加载空格,否则永远不应该执行它。如果空白加载,则将定义whitespace-mode
。
这个警告是emacs编译器限制的结果还是我做错了什么?
答案 0 :(得分:3)
我在这里添加了上面作为评论的回复,仅供记录。
编译器说的是该函数是在编译时定义的,但是当您运行代码时它可能不存在(它告诉您以前在运行代码时必须要求它)。因此,如果您只需要在该程序包中定义的宏,那么eval-when-compile
仅可能是一个好习惯。如果您还需要函数和/或变量,则只需require
包,而不是eval-when-compile
,但始终。{/ p>
答案 1 :(得分:2)
编辑:在这种情况下,代码中没有错误,只是字节编译器不知道函数的定义位置。它不知道whitespace-mode
中定义了whitespace.el
,因为没有什么可以告诉它的。 (联合国)幸运的是,它并不像你现在那么聪明。 : - )
使用require
通常更倾向于使用autoload
。然后你可以忘记require
的所有内容,因为emacs(和字节编译器)将在第一次调用函数时知道如何加载函数。
(autoload 'whitespace-mode "whitespace" nil t)
如果您知道该函数已经加载,您可以使用declare-function
告诉字节编译器在某个文件中定义了一个函数。语法为(declare-function FUNCTION FILE ARGLIST)
。对于你的情况,它将是
(declare-function whitespace-mode "whitespace" (&optional ARG))
我通常在使用它们的defun之前将它们放在正确的位置,但这只是出于组织目的。
当然,如果您放置的内容实际上不是真的(文件没有定义函数),这些中的任何一个都可以掩盖错误,但我认为由于whitespace.el
可能会被删除或改变和加载会失败。我不认为在大多数情况下这种可能性是值得保护的。
答案 2 :(得分:1)
您可以在代码中添加显式检查:
(defun whitespace-redraw ()
(eval-when-compile (require 'whitespace nil t))
(when (and (require 'whitespace nil t)
(fboundp 'whitespace-mode))
(if whitespace-mode
(whitespace-mode 0))
(whitespace-mode 1)))
但这可能会在一段时间后变得麻烦。