Eric Lippertにこれに答えさせましょう。
この時点で明らかな問題は、CPSが非常に優れている場合は、なぜそれをいつも使用しないのかということです。ほとんどのプロの開発者がそれを聞いたことがないのか、あるいは、それを知っている人が、クレイジーなSchemeプログラマーだけが行うことと考えているのですか?
まず第一に、サブルーチン、ループ、try-catch-finallyなどについて考えることに慣れているほとんどの人にとって、デリゲートがこのように制御フローに使用されていることを推論することは簡単ではありません。私は今、CS442からのCPSに関するメモを確認しています。1995年にprofQUOTEを書き留めたことがわかりました。「継続する場合は、頭の上に立って、裏返しにする必要があります」。ダガン教授(*)はそれを言っているのは絶対に正しかった。数日前から、C#式M(B()?C():D())のCPS変換の小さな例に4つのラムダが含まれていたことを思い出してください。誰もが高階関数を使用するコードを読むのが得意ではありません。それは大きな認知的負担を課します。
さらに、特定の制御フローステートメントを言語に焼き付けることの優れた点の1つは、メカニズムによって、呼び出しスタック、戻りアドレス、例外ハンドラーリスト、保護された領域を隠しながら、コードで制御フローの意味を明確に表現できることです。等々。継続により、制御フローのメカニズムがコードの構造で明示的になります。メカニズムに重点を置くと、コードの意味がわかりにくくなります。
では次の記事、彼は非同期かつ継続は互いにまったく同じであるかを説明し、簡単なを取ってのデモンストレーションを乗り越え、(しかし、ブロッキング、)同期ネットワークの運用とasyncronousスタイルでそれを書き換え、必ずすべての隠さをカバーすることそれを正しくするためにカバーする必要がある落とし穴。それは巨大なコードの混乱に変わります。最後の彼の要約:
神聖な善、私たちが作ったなんてひどい混乱です。完全に明確な2行のコードを、これまでにない最もゴージャスなスパゲッティの20行に拡張しました。そしてもちろん、ラベルがスコープ内になく、割り当てエラーがあるため、コンパイルもできません。これらの問題を修正するには、コードをさらに書き直す必要があります。
CPSの長所と短所について私が言っていたことを覚えていますか?
- PRO:単純なパーツから任意に複雑で興味深い制御フローを構築できます–チェックしてください。
- CON:継続による制御フローの具体化は、読みにくく、推論も難しい–チェック。
- CON:制御フローのメカニズムを表すコードは、コードの意味を完全に覆します–チェック。
- CON:通常のコード制御フローからCPSへの変換は、コンパイラーが得意で、他の誰も得意としないものです–チェックしてください。
これは知的運動ではありません。実際の人々は、非同期性を扱うとき、常に上記と道徳的に同等のコードを書くことになります。そして皮肉なことに、プロセッサーがより速く、より安価になったとしても、プロセッサーに縛られないものを待つために私たちはますます多くの時間を費やしています。多くのプログラムで、費やされる時間の多くは、ネットワークパケットがイギリスから日本に移動して再び戻るのを待つか、ディスクがスピンするか、その他を待つためにプロセッサがゼロに固定されています。
さらに、非同期操作をさらに構成したい場合に何が起こるかについても触れていません。ArchiveDocumentsをデリゲートをとる非同期操作にしたいとします。これを呼び出すすべてのコードもCPSで記述する必要があります。汚れが広がるだけです。
非同期論理権を取得することで重要なのは、それだけになるだろう
将来的にはもっと重要な、と私たちは与えられたツールはあなたが作る
「あなたの頭の上に立って、裏返しに自分自身を回す」として教授ダガンは賢明に言いました。
はい、継続渡しのスタイルは強力ですが、その力を上手く利用するには、上記のコードよりも優れた方法が必要です。
両方の記事、およびこのすべての混乱をコンパイラーに移動し、特定の部分を非同期としてマークする特別なキーワードを使用して通常の制御フローとしてコードを記述できるようにする新しいC#言語機能に関する次のシリーズは、読者が読んでも価値があるC#開発者ではありません。私はそうではありませんが、初めてそれに遭遇したときは、それでもまだ非常に啓発的な経験でした。