方案中的递归宏导致意外循环

时间:2018-04-03 14:11:31

标签: scheme lisp racket

有人可以解释为什么这段代码会导致循环?

(define-macro proc
 (lambda (n)
   `(begin
     (display ,n)
     (set! ,n (+ ,n 1))
     (if (< ,n 10)
         (proc ,n)))))

(let ((x 5))
  (proc x))

2 个答案:

答案 0 :(得分:1)

您永远不会停止宏扩展 - 宏评估会在评估之前发生而不是按需提供,因此您无法使用评估时间值进行条件扩展。

换句话说,

(proc x)

扩展为

(begin
 (display x)
 (set! x (+ x 1))
 (if (< x 10)
     (proc x)))

扩展为

(begin
 (display x)
 (set! x (+ x 1))
 (if (< x 10)
     (begin
         (display x)
         (set! x (+ x 1))
         (if (< x 10)
             (proc x)))))

扩展为

(begin
 (display x)
 (set! x (+ x 1))
 (if (< x 10)
     (begin
         (display x)
         (set! x (+ x 1))
         (if (< x 10)
             (begin
                 (display x)
                 (set! x (+ x 1))
                 (if (< x 10)
                 (proc x)))))))

依此类推,无限期。

答案 1 :(得分:0)

proc始终扩展为对proc的调用。如果要有条件地扩展,则必须在宏展开时(未经测试)完成测试:

(define-macro proc 
  (lambda (n) 
    `(begin ,(if (< n 10) `(proc ,(+ n 1)) '())))