Lassen wir Eric Lippert diese Frage beantworten:
Die offensichtliche Frage an dieser Stelle ist: Wenn CPS so großartig ist, warum verwenden wir es dann nicht die ganze Zeit? Warum haben die meisten professionellen Entwickler noch nie davon gehört oder denken diejenigen, die es haben, als etwas, was nur diese verrückten Scheme-Programmierer tun?
Erstens ist es für die meisten Menschen, die es gewohnt sind, über Unterprogramme, Schleifen, Try-Catch-Endlich usw. nachzudenken, einfach schwierig, darüber nachzudenken, dass Delegierte auf diese Weise für den Kontrollfluss verwendet werden. Ich überprüfe gerade meine Notizen zu CPS von CS442 und sehe, dass ich 1995 ein profQUOTE niedergeschrieben habe: „Mit Fortsetzungen muss man sich auf den Kopf stellen und sich von innen nach außen ziehen“. Professor Duggan (*) hat das absolut richtig gesagt. Wir erinnern uns an ein paar Tage zuvor, dass unser kleines Beispiel für die CPS-Transformation des C # -Ausdrucks M (B ()? C (): D ()) vier Lambdas umfasste. Nicht jeder kann Code lesen, der Funktionen höherer Ordnung verwendet. Es bringt eine große kognitive Belastung mit sich.
Darüber hinaus: Eines der schönen Dinge beim Einbetten bestimmter Kontrollflussanweisungen in eine Sprache ist, dass Ihr Code die Bedeutung des Kontrollflusses klar ausdrückt, während die Mechanismen ausgeblendet werden - die Aufrufstapel und Rücksprungadressen sowie Ausnahmehandlerlisten und geschützte Regionen und so weiter. Fortsetzungen machen die Mechanismen des Kontrollflusses in der Struktur des Codes explizit. All diese Betonung des Mechanismus kann die Bedeutung des Codes überwältigen .
Im nächsten Artikel erklärt er, wie Asynchronität und Fortsetzungen genau gleichwertig sind, und geht eine Demonstration durch, in der ein einfacher (aber blockierender) synchroner Netzwerkbetrieb ausgeführt und in asynchronem Stil neu geschrieben wird, wobei sichergestellt wird, dass alle verborgenen Elemente abgedeckt werden Fallstricke, die abgedeckt werden müssen, um es richtig zu machen. Es wird zu einem massiven Durcheinander von Code. Seine Zusammenfassung am Ende:
Heilige Güte, was für ein schreckliches Durcheinander haben wir gemacht. Wir haben zwei Zeilen mit klarem Code zu zwei Dutzend Zeilen der schrecklichsten Spaghetti erweitert, die Sie je gesehen haben. Und natürlich wird es immer noch nicht kompiliert, da die Labels nicht im Geltungsbereich liegen und wir einen eindeutigen Zuweisungsfehler haben. Wir müssten den Code noch weiter umschreiben, um diese Probleme zu beheben.
Erinnerst du dich, was ich über die Vor- und Nachteile von CPS gesagt habe?
- PRO: Beliebig komplexe und interessante Kontrollabläufe können aus einfachen Teilen aufgebaut werden - prüfen.
- CON: Die Überprüfung des Kontrollflusses über Fortsetzungen ist schwer zu lesen und schwer zu begründen - zu überprüfen.
- CON: Der Code, der die Mechanismen des Kontrollflusses darstellt, überwältigt die Bedeutung der Codeüberprüfung vollständig.
- CON: Die Umwandlung des normalen Codesteuerungsflusses in CPS ist die Art von Dingen, in denen Compiler gut sind, und fast niemand anderes ist - überprüfen.
Dies ist keine intellektuelle Übung. Echte Menschen schreiben am Ende immer Code, der moralisch dem oben genannten entspricht, wenn sie sich mit Asynchronität befassen. Und ironischerweise verbringen wir immer mehr Zeit damit, auf Dinge zu warten, die nicht prozessorgebunden sind , obwohl Prozessoren schneller und billiger geworden sind . In vielen Programmen wird ein Großteil der Zeit damit verbracht, den Prozessor auf Null zu setzen und darauf zu warten, dass Netzwerkpakete die Reise von England nach Japan und wieder zurück antreten oder dass sich Festplatten drehen oder was auch immer.
Und ich habe noch nicht einmal darüber gesprochen, was passiert, wenn Sie asynchrone Operationen weiter zusammenstellen möchten. Angenommen, Sie möchten ArchiveDocuments zu einer asynchronen Operation machen, die einen Delegaten benötigt. Jetzt muss der gesamte Code, der ihn aufruft, auch in CPS geschrieben werden. Der Makel breitet sich einfach aus.
Es ist wichtig, die asynchrone Logik richtig zu machen , sie wird in Zukunft nur
noch wichtiger sein, und die Werkzeuge, die wir Ihnen gegeben haben, lassen Sie
„auf dem Kopf stehen und sich auf den Kopf stellen“, wie Professor Duggan mit Bedacht sagte.
Der Continuation-Passing-Stil ist mächtig, ja, aber es muss einen besseren Weg geben, diese Kraft gut zu nutzen als den obigen Code.
Beide Artikel und die folgende Serie über eine neue C # -Sprachenfunktion, die all dieses Durcheinander in den Compiler überträgt und es Ihnen ermöglicht, Ihren Code als normalen Kontrollfluss mit einem speziellen Schlüsselwort zu schreiben, um bestimmte Teile als asynchron zu markieren, sind auch dann lesenswert, wenn Sie Ich bin kein C # -Entwickler. Ich bin es nicht, aber es war immer noch eine ziemlich aufschlussreiche Erfahrung, als ich zum ersten Mal darauf stieß.