Возвращаясь к стилю передачи продолжений. Часть 4: выверни себя наизнанку

Сейчас может возникнуть очевидный вопрос: если CPS является такой классной техникой, то почему бы ею не пользоваться постоянно? Почему большинство профессионалов никогда не слышали об этом, а те, кто слышали, считают, что это нечто безумное, доступное только программистам на Scheme.

Прежде всего, большинству людей сложно думать о сопрограммах, циклах, блоках try-catch-finally и тому подобном и рассматривать делегаты как средство реализации логики управления. Я сейчас просматриваю свои записи о CPS из моего курса CS442 и вижу, что в 1995 году я записал следующее: «С продолжениями вам нужно встать и вывернуть себя наизнанку». Профессор Дугган (Duggan) (*) был абсолютно прав, когда это говорил. Вспомните, что пару дней назад в нашем маленьком примере с преобразованием выражения C# M(B()?C():D()) в CPS мы получили четыре лямбда-выражения. Не каждый может спокойно читать код с функциями высших порядков. Это требует больших умственных усилий.

Более того, важной особенностью конкретных операторов логики управления, встроенных в язык программирования, является то, что они позволяют коду явно выражать намерения логики управления, скрывая механизмы реализации – стек, адрес возврата, список обработчиков исключений, защищенные области (protected regions) и т.п. Продолжения делают механизм логики управления явным в структуре кода. В таком случае акцент на механизме может скрыть значение кода.

Кроме того, генерация четырех лямбда-выражений, содержащих 14 разных особенностей означает, что огромное количество объектов, создаваемых для всех этих замыканий, приведет к очень сложному коду. Большая часть исследований о CPS потрачены на выяснение того, как выполнить CPS-преобразование не создавая массы замыканий.

Итак, если у нормальных людей вызывает сложности чтение CPS-программ, то почему эта тема вообще интересна? Не является ли она всего лишь интеллектуальным упражнением?

Это интересно для меня, поскольку я нахожусь со стороны реализации языков программирования. Если удастся написать компилятор, способный преобразовать код на вашем любимом языке программирования в CPS, и у вас будет вспомогательный код, который знает, как вызывать следующее продолжение, не расходуя стек, тогда, как мы уже видели, мы получим все строительные блоки, необходимые для добавления любых средств управления потоком в виде библиотечных методов. Если вся сложность по преобразованию программы в CPS будет возложена на компилятор, и будет использоваться во время выполнения, это позволит пользователю писать программы в нормальном императивном стиле. Если пользователь захочет добавить новый тип управления потоком выполнения, он сможет написать для этого библиотечные методы. Конечно, мы не собираемся делать это, но это позволит понять, о чем идет речь.

Но это все теория. Среди пользователей языков программирования существует множество программистов, использующих эту методику в разных языках программирования для создания действительно классных вещей, решающих бизнес-задачи, (сегодня, особенно в JScript), но это все еще является весьма экзотической техникой по меркам большинства современных программистов.

Причина, по которой механизм CPS важен для C# программиста, заключается в том, что вы уже знаете, как писать программы в CPS-стиле, просто вы можете не знать это название. Вы наверняка выполняли это в том или ином виде. И вам наверняка это показалось непонятным, ведущим к ошибкам и сложным. Вы наверняка писали программы, использующие асинхронность.

В следующий раз: каково сходство между CPS и асинхронностью? (Подсказка: они похожи практически во всем.)

(*) Профессор Дугган, если вы это читаете, это я, парень в шляпе с вашего курса CS 442 1995 года. Мне потребовалось лишь 10 лет после окончания университета, десять лет проектирования возможностей языка программирования и реализации компилятора для него, чтобы понять ваше объяснение стиля передачи продолжений. Это не говорит о плохом преподавании, которое было просто отличным. Просто очень сложно понять CPS, вы же понимаете.

Оригинал статьи