macrolet 是否禁止在本地定义的宏之间进行递归调用?

Does macrolet prohibit recursive calls among locally defined macros?

在他的书中ANSI Common Lisp, p.320, Paul Graham writes of macrolet"Like flet, the local macros may not call one another."

也许我误解了这一点,但我想不出任何可能是真的。宏不会相互调用,而是相互扩展,宏扩展的性质是这样的,它会一直持续到作用域中定义的所有宏都被扩展掉。

在我尝试过的 Common Lisp 的每个实现中,如下代码都与 Graham 不一致:

(macrolet ((jump (x) `(car ,x))
           (skip (x) `(jump ,x))
           (hop (x) `(skip ,x)))
  (hop '(1 2 3))) 

=> 1

(macrolet ((yin (n x)
             (if (zerop n)
                 `(cdr ,x)
                 `(yang ,(1- n) ,x)))
           (yang (n x)
             (if (zerop n)
                 `(car ,x)
                 `(yin ,(1- n) ,x))))
      (yin 6 '(1 2 3)))

=> (2 3)

格雷厄姆的说法有误吗?

macrolet 定义的宏可以 扩展 以使用同一 macrolet 中定义的不同宏。 macrolet定义的宏直接使用同一个macrolet定义的不同宏是不正确的。例如:

(macrolet ((jump (x) `(car ,x))
           ;; Okay since skip expands into jump.
           (skip (x) `(jump ,x)))
  (skip '(1 2 3))) 

=> 1

相对于

(macrolet ((jump (x) `(car ,x))
           ;; Wrong since skip uses jump directly.
           (skip (x) (jump x)))
  (skip '(1 2 3))) 

=> Error: The function COMMON-LISP-USER::JUMP is undefined.