将变量公开给defun中返回的lambda

时间:2016-03-07 08:28:00

标签: emacs elisp

我正在尝试附加一个密钥处理程序,以便首先执行一个包装函数,检查是否已加载库,如果没有,则在最终执行预期函数之前加载它。

我们的想法是:

(global-set-key (kbd "C-c r")
                (run-or-load-f 'visual-regexp 'vr/replace))

run-or-load-f的位置:

(defmacro run-or-load-f (mode func)
  `(lambda()
     (interactive)
     (run-or-load mode func)))

我遇到的问题是我不知道如何在上面的lambda中公开modefunc 。我甚至不确定我需要一个宏,但看起来确实如此。

为了完成起见,上面的函数run-or-load非常简单:

(defun run-or-load (mode func)
  (unless (fboundp mode)
    (load-library (symbol-name mode)))
  (call-interactively func))

2 个答案:

答案 0 :(得分:3)

不,你的回答允许lambda充当闭包”。

要使lambda像闭包一样,打开lexical-binding作为文件第一行的文件局部变量。请参阅Elisp手册,节点Lexical Binding

你使用反引号和逗号的答案是替换这些变量的值来代替lambda中的变量。也就是说,它删除了那些自由变量,将它们替换为构造(评估)lambda时的

这里使用闭包的好处是,在调用函数时变量可用(不仅仅是在定义它时)。 (如果那时你不需要变量那么这个优势就会消失。)

如果您使用defun而不是defmacro,则闭包的另一个优点是,在编译文件时,结果函数可以自动进行字节编译。

相反,使用反引用的lambda方法,字节编译时的结果只是一个列表:(lambda ...)。编译器无法知道您打算始终将该列表用作函数,因此它不会编译为函数 - 每次调用函数时都会将其计算为列表。 (除非你明确地调用字节编译器来编译它。)

答案 1 :(得分:1)

事实证明,在调用run-or-load时我必须使用不同的语法,这允许lambda像闭包一样:

(defmacro run-or-load-f (mode func)
  `(lambda()
     (interactive)
     (run-or-load ,mode ,func)))