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

时间:2015-08-18 15:16:02

标签: recursion macros common-lisp

在他的书ANSI Common Lisp,第320页中,Paul Graham写道macrolet"与flet一样,本地宏可能不会互相调用。 #34;

也许我误解了这一点,但我无法想到它可能是真的。宏不会相互调用,而是互相扩展,宏扩展的性质是这样的,它一直持续到范围内定义的所有宏都被扩展为止。

以下代码在我尝试使用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)

格雷厄姆的陈述是错误的吗?

1 个答案:

答案 0 :(得分:7)

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.