Function Emacs:钩子是如何工作的?

Function Emacs:钩子是如何工作的?,function,emacs,elisp,hook,Function,Emacs,Elisp,Hook,我已经阅读了不同的教程和手册,但仍然无法将它们组合在一起 据我所知,当我需要在保存旧函数的同时向事件添加新函数时,我会通过调用addhook来添加一个钩子。从添加挂钩上的手动输入: 在钩子列表的开头添加函数(如有必要) 除非可选参数APPEND为非nil 所以钩子只是一个函数列表。但是这个列表看起来怎么样?作品从我的小研究中,我发现除了car和cdr之外,每个cons单元都有一个不可见的未提及的函数指针插槽(可能是索引,没关系)。那么,如何手动创建函数列表并执行它呢?可能是使用addtolist

我已经阅读了不同的教程和手册,但仍然无法将它们组合在一起

据我所知,当我需要在保存旧函数的同时向事件添加新函数时,我会通过调用
addhook
来添加一个钩子。从
添加挂钩上的手动输入:

在钩子列表的开头添加函数(如有必要) 除非可选参数APPEND为非nil

所以钩子只是一个函数列表。但是这个列表看起来怎么样?作品从我的小研究中,我发现除了car和cdr之外,每个cons单元都有一个不可见的未提及的函数指针插槽(可能是索引,没关系)。那么,如何手动创建函数列表并执行它呢?可能是使用
addtolist
函数,但我尝试的所有操作都会触发错误。手册中还包括:

可以像任何其他Lisp变量一样使用setq设置钩子变量

这里有点不对劲,因为指向函数的指针不会被setq复制。即:

(defun myfunc1 () (message "hello"))
(setq onemorefunc 'myfunc1)

执行
(onemorefunc)
,调试器触发后,
setq
只会忽略指针存储的未命名元素的值。

要调用变量中的函数,必须使用
funcall
apply

(funcall onemorefunc)

(apply onemorefunc '())
当Emacs处理钩子变量时,它会在列表中迭代:

(do ((hooks blah-hook (cdr hooks)))
    ((null hooks))
  (funcall (car hooks)))

在您的示例中,您的
setq
仅使
onemorefunc
成为
myfunc1
的另一个名称。钩子需要是一个列表,您需要使用
addhook
将钩子函数添加到该列表中,这是
push
的美化版本,而不是使用
setq
将列表完全替换为函数。提到
setq
已经误导了你,尽管熟悉hook的人很清楚,它告诉了你一些其他正确的东西。它说您可以使用
setq
设置一个钩子变量,而不是钩子本身,您也可以,但它没有明确说明您必须将该钩子变量设置为另一个列表(包含零个或多个函数),而不是函数。因此,假设
my mode start hook
为空以开始:

(add-hook 'my-mode-start-hook #'my-func)
相当于:

(setq my-mode-start-hook (list #'my-func))

在实践中,你应该始终做前者,而不要做后者,除非你确实知道自己在做什么。

此外,有关更多信息,请参阅