Продолжений в Clojure
Я где-то читал, что Рич Хики сказал:
" я думаю, что продолжение может быть аккуратным в теории, но не на практике "
Я не знаком с Clojure.
1. В Clojure не имеют продолжения?
2. Если нет, то разве вам не нужны продолжения? Я видел много хороших примеров, особенно от этого парня. Какова альтернатива?
3. Если да, то есть ли документация?
7 ответов:
Говоря о продолжениях, вы должны различать два различных их вида:
Первоклассные продолжения-Continuation-поддержка, которая глубоко интегрирована в язык (Scheme или Ruby). Clojure не поддерживает первоклассные продолжения.
Continuation-passing – style (CPS) - CPS-это просто стиль кодирования, и любой язык, поддерживающий анонимные функции, позволит этот стиль (который применяется к Clojure тоже).
Примеры:
-- Standard function double :: Int -> Int double x = 2 * x -- CPS-function – We pass the continuation explicitly doubleCPS :: Int -> (Int -> res) -> res doubleCPS x cont = cont (2 * x)
; Call print (double 2) ; Call CPS: Continue execution with specified anonymous function double 2 (\res -> print res)
ЧитайтеПродолжение в Википедии.
Я не думаю, что продолжения необходимы для хорошего языка, но особенно первоклассные продолжения и CPS в функциональных языках, таких как Haskell, могут быть весьма полезны (интеллектуальный пример обратного хода).
Является ли продолжение необходимым признаком в языке?
Нет. Многие языки не имеют продолжений.
Если нет, то разве вам не нужны продолжения? Я видел много хороших примеров, особенно от этого парня. Какова альтернатива?
Стек вызовов
Общее использование продолжений заключается в реализации структур управления для: возврата из функции, выхода из цикла, обработки исключений и т. д. Большинство языков (таких как Java, C++ и т. д.) предоставляют эти функции как часть основного языка. Некоторые языки этого не делают (например, Scheme). Вместо этого эти языки предоставляют континуации в качестве объектов первого класса и позволяют программисту определять новые структуры управления. Таким образом, Scheme следует рассматривать как инструментарий языка программирования, а не полный набор инструментов. язык сам по себе.
В Clojure нам почти никогда не нужно использовать продолжения напрямую, потому что почти все структуры управления предоставляются комбинацией языка/виртуальной машины. Тем не менее, первоклассные продолжения могут быть мощным инструментом в руках компетентного программиста. Особенно в Scheme, продолжения лучше, чем эквивалентные аналоги в других языках (например, пара setjmp/longjmp в C). Эта статья содержит более подробную информацию об этом.
Кстати, это будет интересно узнать, как Рич Хики обосновывает свое мнение о продолжениях. Есть ссылки на это?
Clojure (или, скорее,
clojure.contrib.monads
) имеет продолжение монады; Вот статья, которая описывает его использование и мотивацию .
Абстрактные Продолжения
Продолжение-это абстрактное понятие, которое используется для описания семантики потока управления. В этом смысле они существуют и не существуют (помните, что они абстрактны) в любом языке, предлагающем управляющие операторы (как и любой полный язык Тьюринга), точно так же, как числа существуют (как абстрактные сущности) и не существуют (как материальные сущности).Продолжения описывают управляющие эффекты, такие как вызов/возврат функции, обработка исключений и даже готос. Хорошо обоснованный язык, среди прочего, будет разработан с абстракциями, которые построены на продолжениях (например, исключениях). (То есть хорошо обоснованный язык будет состоять из управляющих операторов, которые были разработаны с учетом продолжений. Конечно, для языка вполне разумно выставлять продолжения в качестветолько управляющей абстракции, позволяя пользователям создавать свои собственные абстракции сверху.)
Продолжение Первого Класса
Если понятие продолжения овеществляется как первоклассный объект в языке, то у нас есть инструмент, на котором можно построить все виды управляющих воздействий. Например, если язык имеет первоклассные продолжения, но не исключения, мы можем построить исключения поверх продолжений.
Задачи с первоклассными продолжениями
Хотя первоклассные продолжения являются мощным и полезным инструментом во многих случаях, есть также некоторые недостатки, чтобы раскрыть их в язык:
Различные абстракции, построенные поверх продолжений, могут привести к неожиданному / неинтуитивному поведению при составлении. Например, блок
finally
может быть пропущен, если я использую продолжение для прерывания вычисления.- если текущее продолжение может быть запрошено в любое время, то время выполнения языка должно быть структурировано таким образом, чтобы можно было создать некоторое представление структуры данных текущего продолжения в любое время. Это накладывает определенную степень нагрузки на бегу-время для функции, которая, к лучшему или худшему, часто считается "экзотической". Если язык размещен (например, Clojure размещен на JVM), то это представление должно быть в состоянии поместиться в рамки, предоставляемые платформой размещения. Могут также существовать другие функции, которые язык хотел бы сохранить (например, взаимодействие C), которые ограничивают пространство решения. Такие проблемы, как эти, увеличивают потенциал "несоответствия импеданса" и могут серьезно осложнить разработку решение производительным.
Добавление первоклассных продолжений к языку
С помощью метапрограммирования можно добавить в язык поддержку первоклассных продолжений. Как правило, этот подход включает преобразование кода в стиль передачи продолжения (CPS), в котором текущее продолжение передается в качестве явного аргумента каждой функции.Например, библиотека Дэвида Нолена delimc реализует разделенные продолжения частей a Программа Clojure через серию макротрансформаций. В том же духе я написал шкив.cps , который является компилятором макросов, преобразующим код в CPS, а также библиотекой времени выполнения Для поддержки большего количества основных функций Clojure (таких как обработка исключений), а также взаимодействия с собственным кодом Clojure.
Одна из проблем с этим подходом заключается в том, как вы обрабатываете границу между нативным (Clojure) кодом и преобразованным (CPS) кодом. В частности, поскольку вы не можете захватить продолжение в машинном коде вам нужно либо запретить (или каким-то образом ограничить) взаимодействие с базовым языком, либо возложить на пользователя бремя обеспечения того, чтобы контекст позволял захватывать любое продолжение, которое они хотят захватить.
Шкив.cps стремится к последнему, хотя некоторые попытки были сделаны, чтобы позволить пользователю управлять этим. Например, можно запретить CPS-коду вызывать машинный код. Кроме того, предусмотрен механизм поставки CPS версий существующих собственные функции.
В языке с достаточно сильной системой типов (такой как Haskell) можно использовать систему типов для инкапсуляции вычислений, которые могут использовать операции управления (т. е. продолжения) из функционально чистого кода.Резюме
Теперь у нас есть информация, необходимая для прямого ответа на ваши три вопроса:
- Clojure не поддерживает первоклассные продолжения из-за практических соображений.
- все языки являются построенный на продолжениях в теоретическом смысле, но немногие языки выставляют продолжения как объекты первого класса. Однако можно добавлять продолжения к любому языку с помощью, например, преобразования в CPS.
- проверьте документацию для delimc и/или шкива.cps .