Emacs:钩子是如何工作的?

3

我已经浏览了不同的教程和手册,但仍然无法将所有东西组合起来。

据我所知,当我需要在旧功能仍然保存时向事件添加新功能时,我通过调用add-hook来添加钩子。从手册中关于add-hook的条目中可以看出:

除非可选参数APPEND为非nil,否则FUNCTION将被添加到挂钩列表的开头

因此,挂钩只是一个函数列表。但这个列表是什么样子的?如何工作?从我的一点研究中,我发现除了carcdr之外的每个cons单元还有一个不可见的未提及的插槽用于函数指针(可能是索引,这并不重要)。那么我该如何手动创建一个函数列表并执行它呢?可能使用add-to-list函数,但我尝试的所有方法都会触发错误。此外,在手册中提到

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

这里有些问题,因为函数指针不会随着setq被复制。也就是说:

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

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

2个回答

2

要调用一个存在变量中的函数,你需要使用funcall或者apply

(funcall onemorefunc)

(apply onemorefunc '())

当Emacs处理一个hook变量时,它会遍历该列表:
(do ((hooks blah-hook (cdr hooks)))
    ((null hooks))
  (funcall (car hooks)))

3
此外,如需更多信息,请查看有关运行钩子的手册。 - Dan

2
在你的例子中,setq 仅仅将 onemorefunc 作为 myfunc1 的另一个名称。钩子需要是一个列表,并且您需要使用 add-hook 将您的钩子函数添加到该列表中,它是 push 的加强版本,而不是使用 setq 完全替换列表中的函数。尽管对于熟悉钩子的人来说很清楚,但是提到 setq 会让人产生误解,它在向您正确地传达一些其他信息。它说您可以使用 setq 设置钩子变量 - 而不是钩子本身 - 并且您可以这样做,但是它没有明确说明您必须将 hook 变量设置为另一个列表(包含零个或多个函数),而不是设置为一个函数。因此,假设 my-mode-start-hook 最初为空列表:
(add-hook 'my-mode-start-hook #'my-func)

等同于:

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

在实践中,除非你确信自己知道自己在做什么,否则应该始终遵循前者而不是后者。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接