如果我做了
(add-hook 'haskell-mode-hook
(lambda ()
(setq indent-tabs-mode t)
(setq tab-width 4)
(message "OK")))在我的~/.emacs.d/init.el中,当我输入haskell-mode时,(lambda ...)确实会被执行。
但是,如果我使用这样的函数:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
(lambda ()
(setq indent-tabs-mode tmode)
(setq tab-width twidth)
(message "OK"))))然后在~/.emacs.d/init.el中稍后调用它,如下所示:
(my-add-hook 'haskell-mode-hook t 4)然后什么都不会发生(即使没有显示"OK“消息)。add-hook是一个不能从defun内部使用的特殊函数吗?我在一个单独的初始化文件中定义了每个项目的设置,该文件检测缓冲区名,并将(lambda ()...)调用添加到相关的主要模式(在上面的示例中是haskell-mode);我想通过使用像上面的my-add-hook这样的瘦包装来减少代码的冗长,但我不知道为什么add-hook如此困难。
EDIT1:添加了用于澄清的代码。
EDIT2:当我尝试使用my-add-hook时,我确实收到了一条“文件模式规范错误:(Variable)”消息。
发布于 2014-10-28 16:52:14
这里有一个简单的解决方法,不需要了解词法绑定:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
`(lambda ()
(setq indent-tabs-mode ,tmode)
(setq tab-width ,twidth)
(message "OK"))))发布于 2014-10-28 16:55:27
您可以使用词法-let重新绑定变量,然后lambda函数将保留它们的值:
(defun my-add-hook (hook tmode twidth)
(lexical-let ((tmode tmode)
(twidth twidth))
(add-hook hook
(lambda ()
(setq indent-tabs-mode tmode)
(setq tab-width twidth)
(message "OK")))))我不确定这是否是最惯用的Emacs代码,但它确实遵循了Emacs文章DynamicBindingVsLexicalBinding中所示的相同模式,该文章将compose定义为:
(defun compose (f g)
(lexical-let ((f f)
(g g))
(lambda (x)
(funcall f (funcall g x)))))https://stackoverflow.com/questions/26613583
复制相似问题