为什么键绑定会导致 Emacs 在启动时执行我的功能?

Why does key binding cause Emacs to execute my function on startup?

我的 Emacs init.el 文件中有一个函数,可以让我从文字源文件重建和字节编译它。它由 defun 包装的 lambda 函数组成,并且完全按照我的预期工作。到目前为止,还不错。

(defun tangle-init-and-reload ()
  "Tangle the code blocks in init.org, byte-compile, and reload."
  (lambda ()
    (interactive)
    ;; Don't run hooks when tangling.
    (let ((prog-mode-hook nil))
      (org-babel-tangle-file (concat user-emacs-directory "init.org"))
      (byte-compile-file (concat user-emacs-directory "init.el"))
      (load-file user-init-file))))

当我读到 Elisp 中的函数时,在我看来我应该能够简单地使用 defun 来定义命名函数并跳过 lambda,所以我删除了 lambda 并在其他方面保持函数不变,如下所示:

(defun tangle-init-and-reload ()
  "Tangle the code blocks in init.org, byte-compile, and reload."
  (interactive)
  ;; Don't run hooks when tangling.
  (let ((prog-mode-hook nil))
    (org-babel-tangle-file (concat user-emacs-directory "init.org"))
    (byte-compile-file (concat user-emacs-directory "init.el"))
    (load-file user-init-file)))

这样写,该函数也能按预期工作——只要我用 M-x tangle-init-and-reload RET 调用它。如果我给它分配一个键绑定,它会在启动时执行,并产生两种不同的副作用之一:对于一些键绑定,它会在 Emacs 仍然打开它时尝试覆盖 init.elc,而对于其他键绑定,它会成功覆盖 init.elc,但随后在重新加载时重新执行,导致无限递归。

我非常乐意坚持使用 lambda 版本,它在键绑定方面没有问题,但我想了解 lambda 正在执行什么魔法 and/or 什么它是关于导致第二个版本在启动时执行的键绑定。谁能解释一下?

无论如何,我的键绑定都处于自定义次要模式,如下所示:

(defvar custom-map (make-keymap)
  "Custom key bindings.")
(define-key custom-map (kbd "C-c C-i") (tangle-init-and-reload))
(define-minor-mode custom-bindings-mode
  "Activates custom key bindings."
  t nil custom-map)

当您定义键绑定时,您将一个键与一个值相关联,在您的例子中是:

(tangle-init-and-reload)

这是一个正常计算的表达式,即。您在关联绑定时调用该函数。

在以前的版本中,评估同一个函数返回一个闭包,你有一个间接级别,所以你建立了一个从键到调用 tangle-init-and-reload.[=13 返回的函数的绑定=]

您可以通过引用简单地给出与绑定关联的函数的名称:

(define-key custom-map (kbd "C-c C-i") 'tangle-init-and-reload)