elisp:使用 lambda 的 defmacro
elisp: defmacro with lambda
抱歉,我尝试了几次,但我无法构建简单的 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 语句使最后一个表单有效?谢谢!
好的,找到一些可行但不确定的东西 - 这是一个优雅的解决方案:
(defmacro wrap-and-define-key (keymap key func)
`(define-key ,keymap ,key '(lambda () (interactive) (eval (list ,func ,key)))))
你不需要宏。
(defun wrap-and-define-key (keymap key func)
(define-key keymap key (lambda () (interactive) (funcall func key))))
(不要引用 lambda 形式。避免 eval
。)
不确定你为什么想要这个,但无论如何,这应该能满足你的要求。
您的宏在第二个示例中不起作用的原因是 '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))))
抱歉,我尝试了几次,但我无法构建简单的 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 语句使最后一个表单有效?谢谢!
好的,找到一些可行但不确定的东西 - 这是一个优雅的解决方案:
(defmacro wrap-and-define-key (keymap key func)
`(define-key ,keymap ,key '(lambda () (interactive) (eval (list ,func ,key)))))
你不需要宏。
(defun wrap-and-define-key (keymap key func)
(define-key keymap key (lambda () (interactive) (funcall func key))))
(不要引用 lambda 形式。避免 eval
。)
不确定你为什么想要这个,但无论如何,这应该能满足你的要求。
您的宏在第二个示例中不起作用的原因是 '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))))