如果我这样做
(add-hook 'haskell-mode-hook
(lambda ()
(setq indent-tabs-mode t)
(setq tab-width 4)
(message "OK")))
在我的~/.emacs.d/init.el
中,当我输入(lambda ...)
时,haskell-mode
会被执行。
但是,如果我使用这样的函数:
(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
a
defun
内无法使用的特殊功能?我有每个项目
在单独的初始化文件中定义的设置,用于检测缓冲区名称
并将(lambda ()...)
次调用添加到相关主要模式(在示例中)
上面,haskell-mode
);我想通过使用瘦来减少代码冗长
像上面的my-add-hook
这样的包装器,但我不知道为什么add-hook
如此
困难的。
EDIT1:添加了澄清的代码。
EDIT2:我尝试使用my-add-hook
时收到“文件模式规范错误:( void-variable tmode)”消息。
答案 0 :(得分:6)
这是一个简单的修复,无需了解词法绑定:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
`(lambda ()
(setq indent-tabs-mode ,tmode)
(setq tab-width ,twidth)
(message "OK"))))
答案 1 :(得分:2)
您可以使用 lexical-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 Lisp代码,但它确实遵循Emacs Wiki文章DynamicBindingVsLexicalBinding中显示的相同模式,该文章将撰写定义为:
(defun compose (f g)
(lexical-let ((f f)
(g g))
(lambda (x)
(funcall f (funcall g x)))))