emacs:符号的函数定义无效:循环

emacs: Symbol's function definition is void: loop

我正在测试在 emacs init.el (Emacs 24.3) 中加载包。我跟着emacs prelude的作者a blog 自动加载包,把那里的代码复制到我的init.el下面。但是,我收到一条关于 loop function/symbol 的错误消息,上面写着:

Symbol's function definition is void: loop

有人可以解释一下如何修复代码吗?

在网上查了一下,好像loopcl-lib里面的一个宏。我的猜测是缺少 loop 的定义,我试图通过添加 (require 'cl-lib) 来解决问题,如代码所示,但错误仍然存​​在。还有其他关于类似错误消息的 SO 问题,例如:ELisp: cl-loop for "Symbol's value as variable is void", Symbol's function definition is 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

cl-lib 包是在 Emacs 24.3 中引入的,它提供了许多 Common Lisp 功能,所有功能都带有 cl- 前缀。在此之前,使用这些功能的唯一方法是需要 cl 库,并使用无前缀的名称,例如loop 而不是 cl-loop。但是,由于可能存在名称冲突,因此不鼓励这样做,通常建议尽可能使用前缀名称。

由于您使用的是 Emacs 24.3,解决此问题的 "correct" 方法是将 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-loopcl-return 是自动加载的。)

或者,您可以添加 (require 'cl) 以访问无前缀的名称,并保持代码不变。这也适用于早期的 Emacs 版本。


我不禁注意到这个函数可以写得更简洁:

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

关于 cl-everycl-libeverycl 的相同问题适用。