I'm attempting to attach a key handler such that a wrapper function is first executed that checks whether a library has been loaded and, if not, loads it before finally executing the intended function.
The idea is to be able to do:
(global-set-key (kbd "C-c r")
(run-or-load-f 'visual-regexp 'vr/replace))
Where run-or-load-f
is:
(defmacro run-or-load-f (mode func)
`(lambda()
(interactive)
(run-or-load mode func)))
The problem I'm having is that I do not know how to expose mode
and func
in the lambda above. I'm not even sure I need a macro but it does seem that way.
For completion's sake, the function run-or-load
above is very simply:
(defun run-or-load (mode func)
(unless (fboundp mode)
(load-library (symbol-name mode)))
(call-interactively func))
No, your answer does not "allow the lambda to act like a closure".
To make the lambda act like a closure, turn on lexical-binding
as a file-local variable in the first line of your file. See the Elisp manual, node Lexical Binding.
What your answer, which uses backquote with comma, does is to substitute the values of those variables in place of the variables within the lambda. That is, it removes those free variables, replacing them by the values they have at the time the lambda is constructed (evaluated).
The advantage of using a closure here is that the variables are available when the function is invoked (not just when it is defined). (If you don't need the variables at that time then this advantage disappears.)
If you had used defun
instead of defmacro
then another advantage of the closure is that the resulting function can be automatically byte-compiled when the file is compiled.
In contrast, with the backquoted lambda approach, the result at byte-compile time is just a list: (lambda ...)
. There is no way for the compiler to know that you intend to always use that list as a function, so it is not compiled into a function - it is evaluated as a list each time the function is invoked. (Unless you explicitly call the byte compiler to compile it.)