Яка різниця між співпрограмою та продовженням та генератором?
Яка різниця між співпрограмою та продовженням та генератором?
Відповіді:
Почну з генераторів, побачивши, як це найпростіший випадок. Як зазначав @zvolkov, вони є функціями / об'єктами, які можна повторно викликати без повернення, але при виклику повернуть (дадуть) значення і призупинять їх виконання. Коли їх знову зателефонують, вони почнуть виходити з місця, коли вони останнім часом призупинили виконання, і робитимуть свою справу знову.
Генератор - це по суті скорочена (асиметрична) коренева програма. Різниця між програмою та генератором полягає в тому, що програма може приймати аргументи після її первинного виклику, тоді як генератор не може.
Трохи важко придумати банальний приклад того, де ти б використовував супроводи, але ось моя найкраща спроба. Візьмемо цей (складений) код Python як приклад.
def my_coroutine_body(*args):
while True:
# Do some funky stuff
*args = yield value_im_returning
# Do some more funky stuff
my_coro = make_coroutine(my_coroutine_body)
x = 0
while True:
# The coroutine does some funky stuff to x, and returns a new value.
x = my_coro(x)
print x
Прикладом використання супротинів є лексери та аналізатори. Без супротивної мови в мові або імітації якось, лексичний і синтаксичний код потрібно змішувати разом, хоча вони справді є двома окремими проблемами. Але, використовуючи супровід, ви можете відокремити код лексики та розбору.
(Я збираюся вирішити різницю між симетричними та асиметричними корументами. Досить сказати, що вони еквівалентні, ви можете конвертувати з однієї в іншу, а асиметричні функції, що найбільше схожі на генератори, - це простіше зрозуміти. Я окреслював, як можна реалізувати асиметричні супроводи в Python.)
Продовження насправді досить прості звірі. Все, що вони є, - це функції, що представляють іншу точку програми, яка, якщо ви її зателефонуєте, призведе до автоматичного переходу в точку, яку представляє функція. Ви використовуєте дуже обмежені версії їх щодня, навіть не усвідомлюючи цього. Наприклад, винятки можна розглядати як певне продовження зсередини. Я наведу вам приклад продовження псевдокоду на основі Python.
Скажімо, у Python була функція, яка називається callcc()
, і ця функція взяла два аргументи, перший - функція, а другий - список аргументів, з якими можна викликати її. Єдиним обмеженням на цю функцію було б те, що останнім аргументом, який вона бере, буде функція (яка буде нашим теперішнім продовженням).
def foo(x, y, cc):
cc(max(x, y))
biggest = callcc(foo, [23, 42])
print biggest
Що трапилося б - це callcc()
, в свою чергу, дзвінок foo()
із поточним продовженням ( cc
), тобто посиланням на пункт програми, на який callcc()
дзвонили. Коли foo()
викликає поточне продовження, це по суті те саме, що говорити callcc()
повернути зі значенням, з якого викликуєте поточне продовження, і коли це робить, він відкочує стек туди, де створено поточне продовження, тобто коли ви зателефонувалиcallcc()
.
Результатом всього цього став би те, що наш гіпотетичний варіант Python надрукував би '42'
.
Я сподіваюся, що це допомагає, і я впевнений, що моє пояснення можна значно покращити!
Спрограма - це одна з декількох процедур, яка по черзі виконує свою роботу, а потім робить паузу, щоб дати контроль іншим спільним процедурам у групі.
Продовження - це "вказівник на функцію", яку ви переходите до якоїсь процедури, яка виконується ("продовжується з"), коли ця процедура виконана.
Генератор (в .NET) - це мовна конструкція, яка може виплюнути значення, "призупинити" виконання методу, а потім перейти з тієї ж точки, коли буде запропоновано наступне значення.
У більш новій версії Python ви можете надсилати значення Генераторам за допомогою generator.send()
, що робить Python Generators ефективно взаємоконтрольним.
Основна відмінність генератора python від іншого генератора, скажімо, greenlet, полягає в тому, що в python ви yield value
можете повернутися лише до абонента. Перебуваючи в greenlet, target.switch(value)
може перевезти вас до конкретної цільової програми та отримати значення, де target
би продовжував працювати.
yield
виклики повинні бути в одній функції, яка називається "Генератор". Ви не можете yield
використовувати підфункцію, тому Python називають напівкоротинами , тоді як Lua має асиметричні функції . (Є пропозиції щодо поширення врожаю, але я думаю, що ті лише