2015-04-29 76 views
1

对不起,我试过几次,我不能建立简单的defmacro - 任何人可以帮助我与:的elisp:与拉姆达defmacro

所以,我想定义的宏将扩展为:

(define-key keymap "*" (lambda() 
          (interactive) 
          (some-func "*"))) 

我想是这样的:

(defmacro wrap-and-define-key (keymap key func) 
    `(define-key ,keymap ,key (lambda() (interactive) (,func ,key)))) 

而且它的工作原理:

(wrap-and-define-key keymap key func) 

但不与

(wrap-and-define-key keymap key 'func) 

工作如何改变defmacro语句,以最后一种形式的工作?谢谢!

+0

为什么它需要是宏?只需定义一个普通的函数。 – Barmar

+0

@barmar是啊,它似乎是更简单和更有用的解决方案。顺便说一句,我只是想在这里了解一些关于defmacro的信息。谢谢! – Rustem

回答

2

你并不需要为这个宏。

(defun wrap-and-define-key (keymap key func) 
    (define-key keymap key (lambda() (interactive) (funcall func key)))) 

(不要引用拉姆达形式,避免eval

不知道为什么你要这样,但无论如何,这应该做你问什么。

+2

尽管我同意,但我认为指出您的代码只能在词法绑定模式下工作很重要。即你需要' - * - 词法绑定:t - * - '在包含这段代码的文件的第一行。 – Stefan

+0

@Stefan感谢您的评论! – Rustem

0

好了,找到工作,但不知道 - 那就是优雅的解决方案:

(defmacro wrap-and-define-key (keymap key func) 
    `(define-key ,keymap ,key '(lambda() (interactive) (eval (list ,func ,key))))) 
2

您的宏不适用于第二个示例的原因是'func作为带引号的参数进行传递,因为对宏的参数不会自动计算。因此,宏中的lambda扩展为:

(lambda() (interactive) ('func key)) 

但是,当以这种方式调用函数名称时,不能引用函数名称。只有lambda或未加引号的符号可以作为函数调用表达式中的第一项出现。如果将宏更改为:

(defmacro wrap-and-define-key (keymap key func) 
    `(define-key ,keymap ,key (lambda() (interactive) (funcall ,func ,key)))) 

它会工作。当lambda被调用时,'func被评估为普通的func符号并传递给funcall。 funcall然后在函数名称空间中查找符号(Elisp是Lisp-2)并调用它。

正如另一个答案中所建议的,您可以使用函数来完成此操作。无论是否启用词汇模式,此功能都将起作用:

(defun wrap-and-define-key (keymap key func) 
    (define-key keymap key `(lambda() (interactive) (funcall ',func ,key))))