В чем разница между сопрограммой и продолжением и генератором?
generator
continuations
coroutine
Мехди Аскари
источник
источник
Ответы:
Я начну с генераторов, посмотрев, как они являются простейшим случаем. Как уже упоминалось @zvolkov, это функции / объекты, которые можно вызывать многократно без возврата, но при вызове возвращает (выдает) значение и затем приостанавливает их выполнение. Когда их снова вызывают, они начнут с того места, где они в последний раз приостанавливают исполнение, и снова сделают свое дело.
Генератор - это, по сути, урезанная (асимметричная) сопрограмма. Разница между сопрограммой и генератором состоит в том, что сопрограмма может принимать аргументы после того, как она была первоначально вызвана, тогда как генератор не может.
Немного сложно придумать тривиальный пример использования сопрограмм, но вот моя лучшая попытка. Возьмите этот (составленный) код Python в качестве примера.
Примером использования сопрограмм являются лексеры и парсеры. Без сопрограмм в языке или каким-либо образом эмулированных, лексический и синтаксический анализ кода должны быть смешаны вместе, хотя на самом деле это две разные проблемы. Но используя сопрограмму, вы можете разделить код лексинга и синтаксического анализа.
(Я собираюсь зачеркнуть разницу между симметричными и асимметричными сопрограммами. Достаточно сказать, что они эквивалентны, вы можете конвертировать из одной в другую, и асимметричные сопрограммы - которые наиболее похожи на генераторы - являются легче понять. Я описал, как можно реализовать асимметричные сопрограммы в Python.)
Продолжения на самом деле довольно простые звери. Все они являются функциями, представляющими другую точку в программе, которая, если вы вызовете ее, заставит выполнение автоматически переключиться на точку, которую представляет функция. Вы используете очень ограниченные версии их каждый день, даже не осознавая этого. Например, исключения можно рассматривать как своего рода продолжение наизнанку. Я дам вам пример продолжения, основанный на Python.
Скажем, у Python была вызванная функция
callcc()
, и эта функция принимала два аргумента, первый из которых был функцией, а второй - список аргументов для вызова. Единственным ограничением для этой функции будет то, что последним аргументом будет функция (которая будет нашим текущим продолжением).То, что произошло бы, это,
callcc()
в свою очередь, вызоветfoo()
с текущим продолжением (cc
), то есть ссылкой на точку в программе, в которойcallcc()
был вызван. Когдаfoo()
вызывается текущее продолжение, это по сути то же самое, что сказать, чтоcallcc()
нужно возвращать значение, с которым вы вызываете текущее продолжение, и когда оно это делает, оно откатывает стек туда, где было создано текущее продолжение, то есть когда вы вызывалиcallcc()
,Результатом всего этого будет то, что наш гипотетический вариант Python будет напечатан
'42'
.Я надеюсь, что это помогает, и я уверен, что мое объяснение может быть улучшено немного!
источник
Сопрограмма - это одна из нескольких процедур, которые по очереди выполняют свою работу, а затем делают паузу, чтобы передать контроль другим сопрограммам в группе.
Продолжение - это «указатель на функцию», которую вы передаете какой-либо процедуре, которая должна быть выполнена («продолжено с помощью») после выполнения этой процедуры.
Генератор (в .NET) - это языковая конструкция, которая может выплевывать значение, «приостанавливать» выполнение метода и затем переходить из той же точки, когда запрашивается следующее значение.
источник
В более новой версии Python вы можете отправлять значения в Generators с помощью
generator.send()
, что делает Python Generators эффективно сопрограммами.Основное отличие между Python Generator и другим генератором, скажем, greenlet, заключается в том, что в python вы
yield value
можете только вернуться обратно к вызывающей стороне. Находясь в гринлете,target.switch(value)
вы можете перейти к определенной целевой сопрограмме и получить значение, при котором онаtarget
будет продолжать работать.источник
yield
вызовы должны быть в одной и той же функции, которая называется «Генератор». Вы не можете сделать этоyield
из подфункции, поэтому Python называют полу-сопрограммами , в то время как у Lua есть асимметричные сопрограммы . (Есть предложения по распространению урожая, но я думаю, что это только мутная вода.)