在emacs lisp中定义一个let宏范围

时间:2018-05-05 15:27:24

标签: macros lisp common-lisp elisp metaprogramming

在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正确地指出fg之前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}};

2 个答案:

答案 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合作进行劫持。)