2017-10-26 9 views
2

私は少しコンセプトに混乱しています。だから私はocamlの継続的な合格スタイル

let rec sumlist lst = 
      match lst with 
      | [] -> 0 
      | (h::t) -> h + (sumlist t) 

継続して、以下の機能を持っている、それは私はまだ何c手段に混乱していますし、それが見て

+1

cは関数です。 'cont_sumlist l(fun x - > x)'はすべてのリスト要素の合計を返します。 –

答えて

3
一般的な答えはすでに cont_sumlistためには、具体的に与えられているが、

  • 我々我々が与えられているcへの "復帰"(すなわち飼料)00です空リストの合計)

  • (h::t)の場合、cont_sumlist tの続きを作成しますt(すなわち、 x)が用意されている場合はhh + x)と組み合わせて、(h::t)についてはcに入力します。

これによりsumlist (h::t) = h + sumlist tを発現しているが、評価チェーンは、それぞれがその上継続関数にその結果を供給し、これらの連続関数の連鎖として明示とします。スタックベースの評価メカニズムに暗黙的に記載されているのとは対照的である。つまりfun x -> c (h + x) = c ∘ (h +)

、我々はリスト[h1; h2; h3; ...]に沿って行くように、継続が徐々にc0 ∘ (h1 +) ∘ (h2 +) ∘ (h3 +) ∘ ...として構成されており、リストは完全によって検索されたとき、最後に0と呼ばれているので、 c0は、ユーザによって一番上のコールに与えられた一番上の継続である。cont_sumlist [x; y; z; ... ; n] c

cont_sumlist [1,2] (fun x -> x) 
= 
(fun x -> (fun x -> (fun x -> x) (1 + x)) (2 + x)) 0 
= 
        (fun x -> x) 
      (fun x ->    (1 + x)) 
(fun x ->         (2 + x)) 0 
= 
(1 + (2 + 0)) 

だから全体巻線および関連巻き戻し及び和はC状擬似コードのように与えられ、直接右から左に計算されないスタックがないことの決定的な違いと

(c ∘ (x +) ∘ (y +) ∘ (z +) ∘ ... ∘ (n +)) 0 
= 
    c (x + (y + (z + .... + (n + 0) ....))) 

になります単純なステップのシーケンス

r = 0; 
    r += n; 
    ....... 
    r += z; 
    r += y; 
    r += x; 
    call c(r);  // call c with r, without expecting c to return; like a jump 

スタック全体の構成は、スタックを巻き上げるのと似ていると言えるかもしれません。そのアプリケーションは、従来のスタックベースの評価の下でのスタックの巻き戻しに対応しています。

CPSは、すべての関数呼び出しが返すことを期待する通常のCのような特殊な関数呼び出しプロトコルを定義しています。

CPS定義の各ケースは、関数の小ステップセマンティクス移行ルールを与えると解釈できます。[] --> 0 ; (h::t) --> (h +)

6

一つの方法を何

let rec cont_sumlist lst c = 
match lst with 
| [] -> (c 0) 
| (h::t) -> cont_sumlist t (fun x -> c (h + x)) 

のように記述することができます継続渡しスタイルは、関数が返されない場合にコードを書く方法を想像することです。関数が計算を行った後に何をしたいのかを指示する、各関数の特別なパラメーターを持つことによって、これまでのことを機能させることができます。つまり、全体の計算の「継続」として機能する関数を渡します。

あなたが与えるコードはまさにこのように書かれており、cが続きます。つまり、関数が意図した計算を行った後に、次に何をするかを指示するのは、呼び出し元が渡す関数です。

継続通過スタイルは完全に一般的です。つまり、すべての計算をこのように表現できます。そして、実際には、通常の機能コードから継続継承スタイルへの機械的な変換があります。 []の場合

関連する問題