在 emacs lisp 中定义一个 let 宏作用域

Defining a let macro scope in emacs lisp

在 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 正确地指出 fhijack-f 之前在 g 中扩展。作为后续行动是否有 hijack-f 这样的:

(f 1) ; => 1
(hijack-f (f 1)) ; => 2
(hijack-f (hijack-f (f 1))) ; => 3

据我所知,你想要的是不可能的,因为 g 不包含对 f 的调用。相反 f 运行 first 并扩展到 g.

的(部分)定义

即:

(defun g (x) (f x))

马上变成

(defun g (x) x)

然后将 g 定义为函数(其值为 (lambda (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)

然后

> (hijack-f (f 1))
2

> (hijack-f (hijack-f (f 1)))
3

以此类推

(正如其他人所指出的,您不能劫持已经用这样的宏编译的代码:您需要让 f 配合劫持才能做到这一点。)