Предупреждение при байтовой компиляции: функция whitespace-mode не может быть определена во время выполнения - PullRequest
4 голосов
/ 18 января 2012

Если я добавлю следующее в 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 или я что-то не так делаю?

Ответы [ 3 ]

3 голосов
/ 18 января 2012

Я добавляю сюда ответ, который я добавил в качестве комментария выше, только для записи.

То, что говорит компилятор, заключается в том, что функция определена во время компиляции, но она может отсутствовать при запускекод (он говорит вам, что вы должны требовать его ранее, когда вы запускаете код).Так что может быть хорошей практикой использовать eval-when-compile только , если вам просто нужны макросы, определенные в этом пакете.Если вам нужны также функции и / или переменные, вы должны просто require пакет, не под eval-when-compile, но всегда.

2 голосов
/ 18 января 2012

EDIT: В этом случае в вашем коде нет ошибки, просто байтовый компилятор не знает, где определена функция.Он не знает, что whitespace-mode определено в whitespace.el, так как ему нечего сказать.(Не) к счастью, это не так умно, как вы еще.: -)

Вместо использования require часто предпочтительнее использовать autoload.Тогда вы можете забыть все о require ing, так как emacs (и байтовый компилятор) будут знать, как загрузить функцию при первом вызове.

(autoload 'whitespace-mode "whitespace" nil t)

Если вы знаете, что функция уже будет загруженаВы можете использовать declare-function, чтобы сообщить байтовому компилятору, что функция определена в определенном файле.Синтаксис (declare-function FUNCTION FILE ARGLIST).Для вашего случая это будет

(declare-function whitespace-mode "whitespace" (&optional ARG))

Я обычно помещаю их прямо перед defun, который их использует, но это только для организационных целей.

Конечно, любой из них может маскировать ошибку, еслито, что вы указали, на самом деле не соответствует действительности (файл не определяет функцию), но я полагаю, что нет никакого способа обойти это, поскольку whitespace.el может быть удален или изменен, и загрузка не удастся.Я не думаю, что в большинстве случаев стоит защититься от случайности.

1 голос
/ 18 января 2012

Вы можете добавить явную проверку к своему коду:

(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)))

Но это может стать громоздким через некоторое время.

...