emacs: определение функции символа недействительно: loop

Я тестирую загрузку пакетов в emacs init.el (Emacs 24.3). Я следил за блогом автора emacs prelude автоматически загружать пакеты и скопировать код в мой init.el как внизу. Тем не менее, я получил сообщение об ошибке loop функция / символ, который говорит:

Symbol's function definition is void: loop

Может кто-нибудь объяснить, пожалуйста, как исправить код?

Я искал в интернете, и кажется, что loop это макрос в cl-lib, Я думаю, что определение для loop отсутствует, и я попытался исправить проблему, добавив (require 'cl-lib), как показано в коде, но ошибка остается. Существуют и другие вопросы SO по аналогичным сообщениям об ошибках, например: ELisp: cl-loop для "Значение символа как переменной void", определение функции Symbol - void: Declare-function. Но сообщения об ошибках различаются по тому, чего не хватает, и ответы в основном предлагают альтернативные маршруты, такие как использование более новой версии emacs.

- код -

(require 'package)
(add-to-list 'package-archives
  '("melpa-stable" . "http://stable.melpa.org/packages/") t)
(package-initialize)

;;; check & load packages
(defvar prelude-packages
  '( haskell-mode )
  "A list of packages to ensure are installed at launch.")

;;(require 'cl-lib) ;debug
(defun prelude-packages-installed-p ()
  (loop for p in prelude-packages
        when (not (package-installed-p p)) do (return nil)
        finally (return t)))

(unless (prelude-packages-installed-p)
  ;; check for new packages (package versions)
  (message "%s" "Emacs Prelude is now refreshing its package database...")
  (package-refresh-contents)
  (message "%s" " done.")
  ;; install the missing packages
  (dolist (p prelude-packages)
    (when (not (package-installed-p p))
      (package-install p))))

(provide 'prelude-packages)
;;; end load packages

1 ответ

Решение

cl-lib Пакет был представлен в Emacs 24.3 и предоставляет ряд возможностей Common Lisp, все с cl- префикс. До этого единственным способом использования этих функций было требование cl библиотека, и используйте имена без префиксов, например, loop вместо cl-loop, Однако это не рекомендуется из-за возможности конфликтов имен, и обычно рекомендуется использовать префиксные имена, если это возможно.

Поскольку вы используете Emacs 24.3, "правильный" способ исправить это - заменить loop с cl-loop а также return с cl-return:

(defun prelude-packages-installed-p ()
  (cl-loop for p in prelude-packages
           when (not (package-installed-p p)) do (cl-return nil)
           finally (cl-return t)))

(Вам не нужно (require 'cl-lib), так как cl-loop а также cl-return загружаются автоматически.)

В качестве альтернативы, вы можете добавить (require 'cl) получить доступ к незафиксированным именам и оставить код как есть. Это также будет работать в более ранних версиях Emacs.


Я не могу не заметить, что эта функция может быть написана более кратко:

(defun prelude-packages-installed-p ()
  (cl-every 'package-installed-p prelude-packages))

Тот же вопрос о cl-every плюс cl-lib против every плюс cl применяется.

Другие вопросы по тегам