Macros 在emacs lisp中定义let宏范围
在emacs lisp中(但也欢迎与common lisp相关的答案),我有一个使用宏的库,我只想在特定上下文中执行时劫持宏的一个参数。基本上我想要的是一个宏:Macros 在emacs lisp中定义let宏范围,macros,lisp,common-lisp,elisp,metaprogramming,Macros,Lisp,Common Lisp,Elisp,Metaprogramming,在emacs lisp中(但也欢迎与common lisp相关的答案),我有一个使用宏的库,我只想在特定上下文中执行时劫持宏的一个参数。基本上我想要的是一个宏: ; My macro. This is a sketch of what I want that doesn't work. (defmacro hijack-f (body) `(macrolet ((f (x) `(f (+ 1 ,x)))) ,@body)) ; Defined in the library, I
; My macro. This is a sketch of what I want that doesn't work.
(defmacro hijack-f (body)
`(macrolet ((f (x) `(f (+ 1 ,x))))
,@body))
; Defined in the library, I don't want to deal with these
(defmacro f (x) x)
(defun g (x) (f x))
所以
(g 1) ; => 1
(hijack-f (g 1)) ; => 2
(hijack-f (hijack-f (g 1))) ; => 3
编辑:@melpomene和@reiner joswig正确地指出,f
在g
中展开,在劫持-f
之前。作为后续行动,存在一个劫持-f
,以便:
(f 1) ; => 1
(hijack-f (f 1)) ; => 2
(hijack-f (hijack-f (f 1))) ; => 3
据我所知,您想要的是不可能的,因为
g
不包含f
的调用。相反,f
首先运行并扩展到g
的(部分)定义
即:
(defun g (x) (f x))
立即变成
(defun g (x) x)
然后将g
定义为一个函数(其值为(λ(x)x)
)
在运行时处理
f
不会影响任何事情,因为在调用g
时,它的调用早已不存在了。如果您希望自己的f
是一个函数而不是一个宏,并且使用CL而不是elisp,那么您需要flet
和这样的宏:
(defmacro hijack-f (&body body)
`(flet ((f (x)
(f (1+ x))))
,@body))
给出了f
的全局定义:
(defun f (x)
x)
然后
等等
(正如其他人所指出的,你不能劫持已经用这样一个宏编译过的代码:你需要让
f
配合劫持。)这行不通,因为宏看不到G的代码。没错,谢谢。如果我跳过g
,直接找到f
的表达式(请参见编辑),怎么样?f
真的是一个宏而不是一个函数吗?为什么?它在库中,实际上它定义了函数和变量等。
> (hijack-f (f 1))
2
> (hijack-f (hijack-f (f 1)))
3