If I do
(add-hook 'haskell-mode-hook
(lambda ()
(setq indent-tabs-mode t)
(setq tab-width 4)
(message "OK")))
in my ~/.emacs.d/init.el
, then the (lambda ...)
does get executed when I enter haskell-mode
.
However, if I use a function like this:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
(lambda ()
(setq indent-tabs-mode tmode)
(setq tab-width twidth)
(message "OK"))))
and then call it later in ~/.emacs.d/init.el
like so:
(my-add-hook 'haskell-mode-hook t 4)
Then nothing happens (even the "OK" message isn't displayed). Is add-hook
a
special function that cannot be used from within a defun
? I have per-project
settings defined in a separate initialization file that detects the buffer name
and adds (lambda ()...)
calls to the pertinent major mode (in the example
above, haskell-mode
); I want to reduce the code verbosity by using a thin
wrapper like my-add-hook
above, but I cannot tell why add-hook
is being so
difficult.
EDIT1: Added code for clarification.
EDIT2: I do get a "File mode specification error: (void-variable tmode)" message when I try to use my-add-hook
.
Here's a simple fix without needing to know about lexical binding:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
`(lambda ()
(setq indent-tabs-mode ,tmode)
(setq tab-width ,twidth)
(message "OK"))))
You can use lexical-let to rebind the variables, then the lambda function will preserve their values:
(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")))))
I'm not sure whether this is the most idiomatic Emacs Lisp code, but it does follow the same pattern shown in the Emacs Wiki article DynamicBindingVsLexicalBinding, which defines compose as:
(defun compose (f g)
(lexical-let ((f f)
(g g))
(lambda (x)
(funcall f (funcall g x)))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With