Macros 在emacs lisp中定义let宏范围

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

在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 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