Абстрактные продолжения
Продолжения — это абстрактное понятие, которое используется для описания семантики потока управления. В этом смысле они и существуют, и не существуют (помните, что они абстрактны) в любом языке, который предлагает управляющие операторы (как и любой полный по Тьюрингу язык), точно так же, как числа существуют (как абстрактные объекты) и не существуют (как материальные сущности).
Продолжения описывают эффекты управления, такие как вызов/возврат функции, обработка исключений и даже переходы. Хорошо обоснованный язык, среди прочего, будет разработан с абстракциями, построенными на продолжениях (например, исключениях). (То есть хорошо обоснованный язык будет состоять из управляющих операторов, которые были разработаны с учетом продолжений. Конечно, для языка совершенно разумно представлять продолжения как единственную управляющую абстракцию. , что позволяет пользователям создавать собственные абстракции поверх них.)
Продолжение первого класса
Если понятие продолжения овеществлено как первоклассный объект в языке, тогда у нас есть инструмент, на котором можно построить все виды эффектов контроля. Например, если в языке есть первоклассные продолжения, но нет исключений, мы можем создавать исключения поверх продолжений.
Задачи с продолжениями первого класса
Несмотря на то, что первоклассные продолжения во многих случаях являются мощным и полезным инструментом, их представление в языке также имеет некоторые недостатки:
- Различные абстракции, построенные поверх продолжений, могут привести к неожиданному/неинтуитивному поведению при составлении. Например, блок
finally
может быть пропущен, если я использую продолжение для прерывания вычисления.
- Если текущее продолжение может быть запрошено в любое время, то среда выполнения языка должна быть структурирована так, чтобы можно было в любое время создать некоторое представление структуры данных текущего продолжения. Это накладывает некоторую нагрузку на время выполнения функции, которая, к лучшему или к худшему, часто считается «экзотической». Если язык размещается (например, Clojure размещается на JVM), то это представление должно соответствовать структуре, предоставляемой платформой размещения. Также могут быть другие функции, которые язык хотел бы поддерживать (например, C-взаимодействие), которые ограничивают пространство решений. Подобные проблемы увеличивают вероятность «несоответствия импеданса» и могут серьезно усложнить разработку эффективного решения.
Добавление первоклассных продолжений к языку
С помощью метапрограммирования в язык можно добавить поддержку первоклассных продолжений. Как правило, этот подход включает в себя преобразование кода в стиль передачи продолжения (CPS), в котором текущее продолжение передается как явный аргумент каждой функции.
Например, библиотека delimc Дэвида Нолена реализует продолжение частей программы Clojure с разделителями посредством серии макропреобразований. Аналогичным образом я написал pulley.cps, макрокомпилятор, преобразующий код в CPS вместе с библиотекой времени выполнения для поддержки дополнительных основных функций Clojure (таких как обработка исключений), а также взаимодействия с собственным кодом Clojure.
Одна проблема с этим подходом заключается в том, как вы обрабатываете границу между собственным (Clojure) кодом и преобразованным (CPS) кодом. В частности, поскольку вы не можете захватить продолжение нативного кода, вам нужно либо запретить (или каким-то образом ограничить) взаимодействие с базовым языком, либо возложить на пользователя бремя обеспечения того, чтобы контекст позволял любому продолжению, которое они хотят захватить, на самом деле быть захваченным.
pulley.cps имеет тенденцию к последнему, хотя были предприняты некоторые попытки позволить пользователю управлять этим. Например, можно запретить коду CPS вызывать собственный код. Кроме того, предусмотрен механизм предоставления CPS-версий существующих встроенных функций.
В языке с достаточно строгой системой типов (таком как Haskell) можно использовать систему типов для инкапсуляции вычислений, которые могут использовать управляющие операции (т. е. продолжения) из функционально чистого кода.
Резюме
Теперь у нас есть информация, необходимая для прямого ответа на ваши три вопроса:
- Clojure не поддерживает первоклассные продолжения по практическим соображениям.
- Все языки построены на продолжениях в теоретическом смысле, но лишь немногие языки представляют продолжения как первоклассные объекты. Однако к любому языку можно добавить продолжения, например, путем преобразования в CPS.
- Ознакомьтесь с документацией для delimc и/или pulley.cps.
person
Nathan Davis
schedule
19.05.2016