关于scheme语言中记忆惰性eval宏的问题

a question about memorized lazy eval macro in scheme language

目前,我一直在读 the scheme programming language Kent Dybvig 写的书。

5.7节中,使用scheme宏系统在scheme中实现了记忆惰性求值。

源代码为

(define-syntax delay
  (syntax-rules ()
    [(_ expr) (make-promise (lambda () expr))]))

(define make-promise
  (lambda (p)
    (let ([val #f] [set? #f])
      (lambda ()
        (unless set?
          (let ([x (p)])
            (unless set?
              (set! val x)
                (set! set? #t))))
        val))))

(define force
  (lambda (promise)
    (promise)))

但是我不明白为什么变量set?需要在程序make-promise中测试两次。 这是书上的原因

The second test of the variable set? in make-promise is necessary in the event that, as a result of applying p, the promise is recursively forced. Since a promise must always return the same value, the result of the first application of p to complete is returned.

我看不懂

谁能给我解释一下?谢谢!

关键是force可能会重新进入自己。也许一个例子可以帮助你理解这一点:

(define x 5)

(letrec ([f (delay
              (if (zero? x)
                  0
                  (begin
                    (set! x (- x 1))
                    (+ (force f) 1))))])
  (force f))

结果将是 0,因为内部 force 调用 returns 0.

如果不进行第二次测试,结果将是5。在这种情况下,每个 (force f) returns 个不同的值。