【シーピーエス、けいぞくわたしスタイル】

CPS(継続渡しスタイル) とは?

💡 「次に何をするか」を荷物として一緒に渡す関数の流儀
📌 このページのポイント
CPS — 通常スタイル vs 継続渡しスタイル 通常スタイル(Direct Style) 呼び出し元 f(x) 関数 f return y return y CPS(継続渡しスタイル) 呼び出し元 f(x, k) 関数 f k(y) 継続 k — 次の処理を受け取って実行 CPSの特徴 ✓ return しない ✓ 次の処理 k を引数で受け取る ✓ コールバック地獄はCPSの 手書きバージョン ✓ async/await は自動CPS変換 ✓ コンパイラの中間表現に利用 ✓ 末尾呼び出し最適化と相性◎ ✓ 制御フローを全て明示できる
通常スタイルとCPSの対比:k(継続)が次の処理を担う
ひよこ ひよこ

CPSって何の略なの?

ペンギン先生 ペンギン先生

Continuation-Passing Styleの略で「継続渡しスタイル」だよ。関数が結果を `return` で返す代わりに、「次にこれをして」という関数(継続)を引数で受け取って、そっちに渡すんだ。

ひよこ ひよこ

普通の `return` と何が違うの?

ペンギン先生 ペンギン先生

通常は `f(x)` → `return y` だけど、CPSでは `f(x, k)` → `k(y)` になるよ。`k` が継続で、`y` を受け取って続きの処理をする関数なんだ。

ひよこ ひよこ

JavaScriptコールバックってそれに似てるね!

ペンギン先生 ペンギン先生

まさに!コールバック地獄は手書きCPSそのものだよ。`async/await` は裏側でCPS変換を自動でやってくれる糖衣構文とも言えるんだ。

ひよこ ひよこ

コンパイラとも関係あるって聞いたことがあるけど?

ペンギン先生 ペンギン先生

コンパイラソースコードをいったんCPS形式の中間表現に変換することが多いよ。そうすると末尾呼び出し最適化例外処理の実装がずっとシンプルになるんだ。

ひよこ ひよこ

全部の制御フローをCPSで書けるなんてすごいね!

ペンギン先生 ペンギン先生

理論的には `if` も `for` も `try/catch` もCPSで表現できるよ。自由と引き換えにコードが深くネストしやすいのが難点だけど、それを解決したのが `async/await` や関数型言語のモナドなんだ。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「CPS(継続渡しスタイル)」って出てきたら「結果を返さず次の処理を引数で渡す関数スタイル」と思えればだいたいOK!
📖 おまけ:英語の意味
「CPS (Continuation-Passing Style)」 = 継続渡しスタイル
💬 "Continuation"は「次にすること」の意。関数が完了後に何をするかを引数で渡すスタイルだよ。
← 用語集にもどる