7

次のSchemeプログラムの動作を理解するのに苦労しています:

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

私が理解しているように、 c は "(display 'X)" の直前に作成された継続にバインドされます。

しかし、c を使用すると、それ自体が変更されるようです。上記の定義により、(予想どおり) IN、X、および OUT が出力されます。

IN
X
OUT

そして、それは手順です:

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

今、私はそれが再び呼び出されたときに X が出力されることを期待していますが、そうではありません!

#;3> (c)
IN
OUT

そして、c はもはや手続きではなく、c の 2 回目の呼び出しは機能しません!

#;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 であることを意味します。したがって、コンテキストに戻り (printing IN)、 99を返して にバインドしc、途中で printOUTします。代わりに 99 を使用するように変更cしたため、3 回目にコールすることはできません。

于 2010-06-13T12:30:33.453 に答える