継続渡しスタイル(CPS)再訪、パート4: 自身をひっくり返す

原文

さてここで分かり切った質問をしよう。 継続渡しスタイルがそんなにすごいなら、なぜ、いつでもこれを使うというようになっていないんだろう? なぜプロの開発者もほとんどはこれまで継続のことを聞いたことがなくて、聞いたことがある人でも、アレなSchemeプログラマーだけが使うものだと考えたりするんだろう?

何よりもまず、サブルーチンや、ループや、try-catch-finallyなどを考えるのに慣れているほとんどの人にとっては、デリゲートがこんな形で制御フローに使われていることについてよく考えることは、単純に難しい。私は今、大学のCS4421という授業で書いた、CPSに関するノートを見返しているのだけど、1995年に書きとめた教授の言葉を見つけた。「継続では、ある意味、自分の頭の上に立って自分自身を裏返しにするようなことをしなければならない。」 Duggan教授2がそう言ったのは本当に正しかった。数日前の記事で、C#の式 M(B() ? C() : D()) をCPSに変化させるというだけの例が、4つのラムダを含むことになったのを思い出してほしい。高階関数を使ったコードを読むのは、みんなが得意なわけではない。理解するために大きな重荷を強要してくるから。

それに、特定の制御フロー文を言語に組み込んでおくことがうれしい理由のひとつは、コールスタックやリターンアドレス、例外ハンドラーリストや保護領域などといった メカニズムを見せない ことで、制御フローの意味をコードで明確に表現できるようになるからだ。 継続は、制御フローのメカニズムをコードの構造の中に明示してしまう。 そのように メカニズム が強調されてしまうと、コードの 意味 がかき消されてしまいかねない。

しかも、たった14文字のコードから4つのラムダが生成されてしまうとすれば、些細でないプログラムの場合、全てのクロージャーのために最終的に作らざるを得ないオブジェクトの数が巨大になりかねないということになる。CPSに関するたくさんの研究が、クロージャを無数に作ることなくCPS変換を行う方法を見つけ出そうと検討するものだった。

では、普通の人にはCPSプログラムを読み書きするのが困難だとすれば、なぜ、これが面白いのか? 単に知的なエクササイズでしかないのだろうか?

私が 継続を面白いと思う理由は、私が言語の 実装 をする側の人間だからだ。もし、好きな言語をCPSに変換するコンパイラーを書くことができて、スタックを消費せずに次の継続をディスパッチする方法を知っているオーケストレーターがあるなら、ここまで説明した通り、その言語に好きな制御フローをライブラリー呼び出しとして追加するための材料はすべてそろっている。プログラムをCPSに変換するという面倒な作業はコンパイラーに任せ、そして、変換結果はランタイムに処理させよう。そうすればユーザーは普通の命令的スタイルでプログラムを書くことができる。ユーザーが新しい種類の制御フローを追加したいと思うなら、変わった制御フローでもライブラリーメソッドとして記述できる。もちろんわざわざそんなことをしなくてもいいのだけど、技術を理解することは人格形成につながるので。

とはいえ継続はまだ、かなりコンピューターサイエンスっぽい。言語の 利用 をする側でも、非アカデミックなプログラマーがビジネス上の問題を解決するために、いろいろな言語(最近は特にJScript)でcall-with-current-continuation機能を使って何か本当にものづくりをすることもだんだん増えてきてはいる。ただ、大部分の主流な業務プログラマーの基準では、まだまだ風変わりな技術である。

CPSがC#プログラマーにも無関係ではない理由は、多分C#プログラマーはすでにCPSプログラムを書く方法をわかっているからだ; たとえそれがCPSと呼ばれていることを知らなかったとしても、である。多分あなたも、どこかでそれをしたことがあるはずだ。そしてその時、それって混乱のもとで、エラーを起こしやすくて、難しいなあと思っただろう。 あなたにも、非同期を使ったプログラムを書かなければならなかったことはあるんじゃないだろうか。

次回予告:非同期とCPSは、どこでどう関連しあうというのか? (ヒント:ほとんどすべて。)


インデックスへ戻る


  1. (訳注)Eric Lippertが学んだカナダのウォータールー大学には、2018年現在もまだCS442の授業があるようだ。そしてシラバスにはちゃんと「継続(continuations)」「コルーチン(coroutines)」の記載がある。 

  2. Duggan教授、あなたがこれを読んでいるならば、ねえ、私です。1995年のあなたのCS 442の授業にいた帽子の男です。あなたがcontinuation passing styleについてした説明を私が理解するには、卒業したあとたったの10年しかかかりませんでした――プログラミング言語機能を設計して、それらのコンパイラを実装する10年でした――。これはあなたの教え方に何か問題があったからではありません。あなたの説明はすばらしかったです。単に、CPSについてあなたのような頭脳を持つのが難しいというだけですよ? 


Last Update: 2018-06-30 08:27:12