4

私はこのコードを読もうとしています:

(define list-iter
  (lambda (a-list)
    (define iter
      (lambda ()
        (call-with-current-continuation control-state)))
    (define control-state
      (lambda (return)
        (for-each
          (lambda (element)
            (set! return (call-with-current-continuation
                           (lambda (resume-here)
                             (set! control-state resume-here)
                             (return element)))))
          a-list)
        (return 'list-ended)))
    iter))

call-with-current-continuationこの例でどのように機能するかを誰か説明できますか?

ありがとう

4

3 に答える 3

3

の本質call-with-concurrent-continuation、またはcall/cc略して、プログラムの実行中にチェックポイントまたは継続を取得する機能です。次に、関数のようにそれらを適用することにより、それらのチェックポイントに戻ることができます。

継続が使用されていない簡単な例を次に示します。

> (call/cc (lambda (k) (+ 2 3)))
5

継続を使用しない場合、違いを区別するのは困難です。これが実際に使用する場所です。

> (call/cc (lambda (k) (+ 2 (k 3))))
3
> (+ 4 (call/cc (lambda (k) (+ 2 3))))
9
> (+ 4 (call/cc (lambda (k) (+ 2 (k 3)))))
7

継続が呼び出されると、制御フローは継続が取得された場所にジャンプして戻りcall/ccます。call/cc式は、に渡されるものによって埋められる穴と考えてくださいk

list-iterはかなり複雑な使用法であり、使用call/ccを開始するのは難しいかもしれません。まず、使用例を次に示します。

> (define i (list-iter '(a b c)))
> (i)
a
> (i)
b
> (i)
c
> (i)
list-ended
> (i)
list-ended

これが起こっていることのスケッチです:

  1. list-iter引数のないプロシージャを返しますi
  2. i呼び出されると、すぐに継続を取得してに渡しcontrol-stateます。にバインドされたその継続returnが呼び出されると、呼び出した人にすぐに戻りますi
  3. リスト内の各要素について、新しい継続を取得し、の定義control-stateをその新しい継続で上書きします。つまり、次にステップ2が実行されたときに、そこから再開します。
  4. control-state次回の設定後、リストの現在の要素をreturn継続に戻し、リストの要素を生成します。
  5. が再度呼び出されたら、がリスト全体の作業を完了するiまで、手順2から繰り返します。for-each
  6. returnで継続を呼び出し'list-endedます。control-stateは更新されないため、呼び出されるたびに戻り続けます'list-endedi

私が言ったように、これはかなり複雑な使用法ですがcall/cc、これでこの例を理解するのに十分だと思います。継続についてより穏やかに紹介するには、TheSeasonedSchemerを選択することをお勧めします。

于 2011-04-12T03:17:27.897 に答える
0

これは本質的に次のとおりです。

(define (consume)
  (write (call/cc control)))

(define (control ret)
   (set! ret (call/cc (lambda (resume)
                        (set! control resume)
                        (ret 1))))
   (set! ret (call/cc (lambda (resume)
                        (set! control resume)
                        (ret 2))))
   (set! ret (call/cc (lambda (resume)
                        (set! control resume)
                        (ret 3)))))

(consume)
(consume)
(consume)

理解しやすいことを願っています。

于 2015-06-27T15:37:14.653 に答える
0

基本的に、関数fをパラメーターとして取りf、プログラムの現在のコンテキスト/状態に適用されます。

ウィキペディアから:
(define (f return)
(return 2)
3)

(display (f (lambda (x) x))) ; displays 3

(display (call-with-current-continuation f)) ; displays 2

したがって、基本的に、f が current-continuation (cc) なしで呼び出されると、関数は 2 に適用され、次に 3 が返されます。current-continuation を使用すると、パラメーターは 2 に適用されます。 current-continuation が呼び出されたため、2 を返します。これを使用して、リターンを生成したり、実行フローを一時停止したりできます。

C を知っている場合は、次のように考えてください。C では、関数へのポインターを使用できます。また、返品メカニズムもあります。関数が受け取るのと同じ型のパラメーターを戻り値が受け取ったとします。そのアドレスを取得して、そのアドレスを変数に格納するか、パラメーターとして渡し、関数が返されるようにすることができるとします。スロー/キャッチを模倣するために、またはコルーチンのメカニズムとして使用できます。

于 2011-04-12T03:22:26.880 に答える