7

我在理解以下 Scheme 程序的行为时遇到了一些麻烦:

(define c
  (dynamic-wind
    (lambda () (display 'IN)(newline))
    (lambda () (call/cc (lambda (k)
                     (display 'X)(newline)
                     k)))
    (lambda () (display 'OUT)(newline))))

据我了解, c 将绑定到在“(显示'X)”之前创建的延续。

但是使用 c 似乎会修改自己!上面的定义打印(如我所料)IN、X 和 OUT:

IN
X
OUT

这是一个程序:

#;2> c
#<procedure (a9869 . results1678)>

现在,我希望当它再次被调用时,X 会被打印出来,但事实并非如此!

#;3> (c)
IN
OUT

现在 c 不再是一个过程,并且第二次调用 c 将不起作用!

#;4> c    ;; the REPL doesn't answer this, so there are no values returned
#;5> (c)

Error: call of non-procedure: #<unspecified>

        Call history:

        <syntax>            (c)
        <eval>              (c)    <--

我期待对 (c) 的每次调用都会做同样的事情——打印 IN、X 和 OUT。我错过了什么?

4

1 回答 1

11

在 Racket 中运行它会更有帮助:

-> (define c
     (dynamic-wind
       (lambda () (display 'IN)(newline))
       (lambda () (call/cc (lambda (k)
                             (display 'X)(newline)
                             k)))
       (lambda () (display 'OUT)(newline))))
IN
X
OUT
-> c
#<continuation>
-> (c)
IN
OUT
define-values: context (defining "c") expected 1 value, received 0 values
-> (c 99)
IN
OUT
-> c
99

请特别注意,它c绑定到一个延续值——因为您的表达式k作为值返回。而k它本身就是值表达式的延续,这意味着这个延续是等待获取要绑定的值的延续c。因此,调用它需要一个值,正如 Racket 所要求的那样,这有助于澄清这里发生的事情(MIT 方案似乎默默地将其视为未指定)。无论如何,在 99 上应用这个延续意味着该表达式的返回值是 99 - 所以你跳回上下文(打印IN)并返回 99以绑定到c,然后OUT在退出时打印。您现在已经修改c为使用 99,因此您不能第三次调用它。

于 2010-06-13T12:30:33.453 回答