1

私はラケットを使用4し、次の単純なコードの結果を得ました。

(let/cc done
  ((let/cc esc
     (done (+ 1 (let/cc k
                  (esc k)))))
   3))

このコードを段階的に実行するつもりでした。

まず、最初のものを次のようなlet/cc形式に変更しました。call/cc

(call/cc (λ (done)
           ((let/cc esc
              (done (+ 1 (let/cc k
                           (esc k)))))
            3)))

もちろん、これ4も生産します。

第二に、私は次の4つのステップを行うcall/ccというインターネットのメカニズムを見つけたので:call/cc

  1. 現在の継続をキャプチャします。
  2. 引数を 1 つ取る関数を構築し、Cその引数値で現在の継続を適用します。
  3. この関数を引数としてexpr--- に渡します。つまり、 を呼び出します(expr C)
  4. を呼び出さ(expr C)ない限り、 を評価した結果を返します。この場合、に渡された値が返されます。exprCC

したがって、最初のcall/ccように上記の手順に従いました。

  1. 現在の継続はアイデンティティです。
  2. Cを指し(λ (x) x)ます。
  3. exprであるため(λ (done) ((let/cc esc (done (+ 1 (let/cc k (esc k))))) 3))、次の(expr C)とおりです。

    ((λ (done)
       ((let/cc esc
          (done (+ 1 (let/cc k
                       (esc k)))))
        3))
     (λ (x) x))
    
  4. 上記のコードの結果値を返すために、racket で上記を実行します。

ただし、上記のコード (私が変更) は実行されず、エラーが発生します。

> application: not a procedure;
>
> expected a procedure that can be applied to arguments
>
>  given: 4
>
>  arguments...:
>
>   3

私が間違ったことをしてください。私は継続の概念を混乱させています。ありがとう。

4

2 に答える 2

1

call/ccインタープリターが CPS を実行しないインタープリターでさえ、そのサブツリーで実行するのを見た場合。コードは次のようになります。

((λ (done)
   ((λ (esc)      
      ((λ (k) (esc k))
       (λ (r) (k+ done 1 r))))
    (λ (v) (v 3))))
 values)


; k+ implementation (+, but CPS) 
(define (k+ k . args)
  (k (apply + args)))
于 2015-12-16T09:03:44.030 に答える