Интересная дискуссия о различии между обратными вызовами и продолжениями SO подтолкнула этот вопрос. По определению, продолжение является абстрактным представлением логики, необходимой для завершения вычисления. В большинстве языков это проявляется как процедура с одним аргументом, которой вы передаете любое значение, требующее дальнейшей обработки.
На чисто функциональном языке (где все функции являются чистыми и первоклассными гражданами), я думаю, что продолжение может быть полностью смоделировано как функция. Это, в конце концов, как я раньше понимал продолжения до этого момента. Тем не менее, мир полон состояния (вздох ..), и поэтому общее определение не требует, чтобы состояние программы захвата продолжения - это только охватывает намерение.
Чтобы помочь моему пониманию, можно ли привести пример на функциональном языке, где продолжение выражено более абстрактно, чем функция? Я знаю, что Scheme позволяет вам получить текущее продолжение первоклассным способом (call / cc), но даже в этом случае кажется, что процедура с одним аргументом, переданная в call / cc, просто получает текущее продолжение в форме другого Процедура аргумента, к которой функция call / cc'd может применить свой результат.
Ответы:
ТЛ; др; Типом является главной абстракцией над продолжением
Продолжением является тип его входов и выходов.
Самое близкое, что вы найдете к продолжению, не основанному на процедурах, - это, вероятно, монада продолжения в Haskell, поскольку она выражается в виде типа, для которого многие функции могут использоваться для взаимодействия с типом для прерывания, возобновления, возврата и т. Д.
Вы можете инкапсулировать это замыкание в тип, такой как
Cont
тип в Haskell, где вы получаете абстракцию монады как «абстракцию более высокого уровня», и есть другие формы абстракции над продолжениями, которые вы получаете, когда вы смотрите на продолжение как на тип вместо просто процедура , напримерЗакрытие против Процедуры
В конце дня вы в основном правы; продолжение - это «процедура», хотя я бы скорее назвал это закрытием. Часто продолжения лучше всего выражать как замыкания первого класса, которые окружают связанную среду. В чистом функциональном языке вы можете сказать, что это не особенно разумно, потому что у вас нет ссылок; это верно, но вы можете заключить значения, и одно присваивание делает вложение значения и ссылки в одно и то же. Это рождает в Хаскеле:
В языке, в котором отсутствует способность заключать в себе связывающую среду, технически могут отсутствовать замыкания первого класса, но даже в этом случае существует некоторая среда (обычно глобальная), доступная для замыкания.
Поэтому я бы сказал, что более точно описать продолжение как: замыкание, используемое определенным образом.
Вывод
На вопрос "Возможно ли продолжение каким-либо образом, кроме процедуры?" Нет. Если у вас нет функций первого класса, вы действительно не можете иметь продолжения как таковые (да, указатели на функции считаются функциями первого класса, так что в качестве альтернативы может быть достаточно произвольного доступа к памяти).
Теперь вопрос «Есть ли способы выразить продолжение более абстрактным способом, чем процедура?» Выражение его как типа дает вам гораздо большую абстракцию, позволяя вам обрабатывать продолжение в самых общих чертах, так что вы можете взаимодействовать с продолжением многими другими способами, а не просто выполнять его.
источник
Один пример, который вам может понравиться, это сопрограммы. Например, сопрограммы из Lua или итераторы / генераторы из Python или C # по мощности похожи на однократные продолжения (продолжения, которые можно вызывать только один раз), но это продолжение явно не превращается в функцию. Вместо этого у вас есть способы продвинуть сопрограмму до следующего выражения «yield».
Например, рассмотрим следующую программу на Python:
Это похоже на следующую программу Javascript с явными обратными вызовами:
Пример Javascript довольно шумный, потому что каждый шаг должен возвращать следующее продолжение в дополнение к возвращаемому значению (в Python отслеживает продолжение внутри ите
источник