5

http://community.schemewiki.org/?call-with-current-continuationからのコルーチンの次の例を見ています。

 (define (hefty-computation do-other-stuff) 
    (let loop ((n 5)) 
      (display "Hefty computation: ") 
      (display n) 
      (newline) 
      (set! do-other-stuff (call/cc do-other-stuff)) ; point A
      (display "Hefty computation (b)")  
      (newline) 
      (set! do-other-stuff (call/cc do-other-stuff)) 
      (display "Hefty computation (c)") 
      (newline) 
      (set! do-other-stuff (call/cc do-other-stuff)) 
      (if (> n 0) 
          (loop (- n 1))))) 

余分な作業:

 ;; notionally displays a clock 
 (define (superfluous-computation do-other-stuff) 
    (let loop () 
      (for-each (lambda (graphic) 
                  (display graphic) 
                  (newline) 
                  (set! do-other-stuff (call/cc do-other-stuff))) 
                '("Straight up." "Quarter after." "Half past."  "Quarter til.")) ; point B
      (loop))) 


(hefty-computation superfluous-computation) 

call/cc を初めて使用する場合、コンテキストはどのようなものになるはずですか? コンテキストとは、callcc のジャンプの結果、どこに「戻る」べきかということです。

私が理解していることから、最初に call/cc を呼び出すと、do-other-stuff は本質的に余分な計算のコードを実行し、set の直後のポイントにジャンプするプロシージャになります! (ポイントA)。2 回目は、「ポイント B にジャンプ」動作を「ポイント A にジャンプしてコンテキストを実行するか、ポイント A に続く任意のコード」をラップします。これは正しいです?

セットの場合、このコードは機能しないようです。実際に起こりました。それともセットですか!このコードが機能するために必要ですか?

何が起こっているかを視覚的に表現することは本当に役に立ちます。

4

1 に答える 1

4

のコンテキストcall/ccは、どこcall/ccから呼び出されているかです。コードを以前の場所にジャンプして戻り値に置き換えるようなものをほとんど考えることができます。call/ccgoto(call/cc whatever)

call/cc基本的には、「この機能を実行して、ここに戻って他のことを忘れるために手放しましょう」と言っています。

call/cc初めて理解しようとしたときに、このコードが非常にわかりにくいことがわかったので、単純化されたコルーチンの例を見てみましょう。

(define r1
  (lambda (cont)
    (display "I'm in r1!")
    (newline)
    (r1 (call/cc cont))))

(define r2
  (lambda (cont2)
    (display "I'm in r2!")
    (newline)
    (r2 (call/cc cont2))))

これは、コードとまったく同じ概念です。しかし、それははるかに簡単です。

この場合、(r1 r2)これをプリントと呼ぶと

I'm in r1
I'm in r2
I'm in r1
I'm in r2    
I'm in r1
I'm in r2    
I'm in r1
I'm in r2
...

なんで?r1最初に r2 を取り込むためcont、r1 にあることが通知されます。そして、(call/cc cont)akaの結果で自分自身を再帰します(call/cc r2)

さて、これのリターンは何ですか?well(call/cc r2) は r2 の実行を開始し、それが r2 にあることをアナウンスしてから、 の結果で自分自身を再帰します(call/cc cont2)。わかりました、また何cont2ですか?cont2の前のその式の続きでしたr1。したがって、ここで呼び出すと、現在いる場所に継続を返します。次に、r2 で行っていたことをすべて忘れて、r1 の実行に戻ります。

これが今も繰り返されr1ています。何かをアナウンスしてから、r2 の前の場所に戻り、前の式を使用して、元(call/cc cont2)の場所への続きを返し、r1陽気な無限ループを続けます。

コードに戻る

あなたのコードでは、概念はまったく同じです。実際superfluous-computation、立ち止まって考えてみると、上記の関数とほとんど同じです。では、set!s はどうしたのでしょうか。このコードでは、 の値をdo-other-work最新の継続に変更するだけです。それでおしまい。私の例では、再帰を使用しました。この例では、 を使用していますset!

于 2012-11-12T05:39:27.923 に答える