在emacs lisp中(但是也欢迎与常见的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
之前hijack-f
展开了hijack-f
。作为后续行动,有一个(f 1) ; => 1
(hijack-f (f 1)) ; => 2
(hijack-f (hijack-f (f 1))) ; => 3
,以便:
int a [][] = {{0,1,0},
{0,1,1},
{2,1,0}};
答案 0 :(得分:2)
据我所知,您想要的是不可能的,因为g
不包含f
的调用。相反,f
首先运行 并扩展为g
的定义(部分)。
那是:
(defun g (x) (f x))
立即变成
(defun g (x) x)
然后将g
定义为函数(其值为(lambda (x) x)
)。
在运行时与f
混淆并不会影响任何事情,因为在您调用g
时它的调用已经过去了。
答案 1 :(得分:0)
如果您对f
成为一个函数而不是一个宏感到高兴,并且使用CL而不是elisp,那么您将追随flet
和这样的宏:
(defmacro hijack-f (&body body)
`(flet ((f (x)
(f (1+ x))))
,@body))
鉴于f
的全球定义:
(defun f (x)
x)
然后
> (hijack-f (f 1))
2
> (hijack-f (hijack-f (f 1)))
3
等等。
(正如其他人所指出的那样,你不能劫持已经用这样的宏编译的代码:你需要让f
合作进行劫持。)