Продолжение (информатика)Продолжение (англ. continuation) — абстрактное представление состояния программы в определённый момент, которое может быть сохранено и использовано для перехода в это состояние. Продолжения содержат всю информацию, чтобы продолжить выполнения программы с определённой точки; состояние глобальных переменных обычно не сохраняется, однако для функциональных языков это несущественно (например, выборочное сохранение и восстановление значений глобальных объектов в Scheme достигается отдельным механизмом dynamic-wind). Продолжения похожи на Первый язык, реализовавший концепцию продолжений — Scheme, позднее встроенная поддержка продолжений появилась в ряде других языков. ОпределенияФормально, Более наглядно, продолжение — это «вся оставшаяся часть программы от данной точки», или «функция, которая никогда не возвращает управление в точку своего вызова»[1]. В курсах функционального программирования объяснение понятия продолжения часто сводится к «расширению (усложнению) понятия сопрограммы», но в дидактическом смысле такое объяснение считается бесполезным[1]. Причина трудности объяснения концепции заключается в том, что продолжения фактически являются альтернативным обоснованием понятия «поведения» («вызова» в самом широком понимании), то есть несут иную семантическую модель, и в этом смысле начальный переход от «обычного» функционального программирования к программированию с интенсивным использованием продолжений можно сравнить с начальным переходом от императивного программирования к функциональному. Продолжения обеспечивают математическое обоснование всего порядка выполнения программы, от Программирование в стиле передачи продолженийПрограммирование в стиле передачи продолжений (англ. continuation-passing style, CPS) — это стиль программирования, при котором передача управления осуществляется через механизм продолжений. Стиль CPS впервые представили Джеральд Джей Сассман[англ.] и Гай Стил-младший[англ.], одновременно с языком Scheme. Программу в «классическом стиле» зачастую можно переписать в стиле передачи продолжений. Например, для задачи вычисления гипотенузы прямоугольного треугольника с «классическим» кодом на Haskell: pow2 :: Float -> Float
pow2 a = a ** 2
add :: Float -> Float -> Float
add a b = a + b
pyth :: Float -> Float -> Float
pyth a b = sqrt (add (pow2 a) (pow2 b))
можно добавить один аргумент типа pow2' :: Float -> (Float -> a) -> a
pow2' a cont = cont (a ** 2)
add' :: Float -> Float -> (Float -> a) -> a
add' a b cont = cont (a + b)
-- типы a -> (b -> c) и a -> b -> c эквивалентны, поэтому CPS-функцию можно
-- рассмотреть как функцию высшего порядка от одного аргумента
sqrt' :: Float -> ((Float -> a) -> a)
sqrt' a = \cont -> cont (sqrt a)
pyth' :: Float -> Float -> (Float -> a) -> a
pyth' a b cont = pow2' a (\a2 -> pow2' b (\b2 -> add' a2 b2 (\anb -> sqrt' anb cont)))
В функции Стандартная haskell-библиотека в модуле Control.Monad.Cont содержит тип pow2_m :: Float -> Cont a Float
pow2_m a = return (a ** 2)
-- функция cont поднимает обычные CPS функции в монаду
pyth_m :: Float -> Float -> Cont a Float
pyth_m a b = do
a2 <- pow2_m a
b2 <- pow2_m b
anb <- cont (add' a2 b2)
r <- cont (sqrt' anb)
return r
Также данный модуль содержит функцию pyth_m :: Float -> Float -> Cont a Float
pyth_m a b = callCC $ \exitF -> do
when (b < 0 || a < 0) (exitF 0.0) -- when :: Applicative f => Bool -> f () -> f ()
a2 <- pow2_m a
b2 <- pow2_m b
anb <- cont (add' a2 b2)
r <- cont (sqrt' anb)
return r
Примеры CPS в Scheme:
В «чистом» CPS фактически не существует самих продолжений — всякий вызов оказывается хвостовым. Если язык не гарантирует оптимизации хвостовых вызовов (англ. Tail call optimization, TCO), то при каждом вложенном вызове Ограниченные и неограниченные продолженияСуществует несколько разновидностей продолжений. Наиболее распространённая из них — неограниченные продолжения (undelimited continuations), реализуемые с помощью функции Поддержка языками программированияМногие языки программирования предоставляют эту возможность под различными именами, например:
В любом языке, поддерживающем замыкания, можно писать программы в стиле передачи продолжений и вручную реализовать Примечания
Ссылки
|