elisp:与lambda的defmacro

时间:2015-04-29 23:52:36

标签: emacs 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语句以使最后一个表单正常工作?谢谢!

3 个答案:

答案 0 :(得分:2)

你不需要一个宏。

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

(不要引用lambda表格。避免使用eval。)

不确定为什么要这样,但无论如何,这应该按照你的要求做。

答案 1 :(得分: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))))

答案 2 :(得分:0)

好的,找到一些有效但不确定的东西 - 这是一个优雅的解决方案:

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