LINUX.ORG.RU

Линеаризация кода и, следовательно, превращение его в более наглядный и простой вид. Типичный юзкейс корутин это event driven приложения, где нужно выполнять последовательность действий по мере поступления событый.

Без корутин нужно между событиями как-то сохранять состояние, например так

event_handler( event, data, state) {

   if(state = STATE_1) {
       // делаем что-то
       state = STATE_2
   } else

   if(state == STATE_2) {
      ...
       state = STATE_3
   }

   // и т.п.
}

С корутинами всё могло бы выглядеть проще

handler() {
    a = read_data();

    // обрабатываем данные a

    send_data(a);

    // и т.п.    

}

На практике первый вариант получается занчительно сложнее чем здесь в примере.

mashina ★★★★★
()

http://fprog.ru/lib/ - Паттерны использования «call with current continuation

больше - в 7-м номере Практики функционального программирования на этой неделе

ott ★★★★★
()

Всем спасибо, все ссылки очень крутые ☺

tensai_cirno ★★★★★
() автор топика
Ответ на: комментарий от WFrag

Понятно что async это частный случай. И им многие пользуются (да у меня сама софтина, которую пишу на руби состоит на 90% из async i/o и корутин). Только есть желание разобраться в этом всём, как работает и какие техники еще используют это.

tensai_cirno ★★★★★
() автор топика

Монада Async в F# целиком состоит из продолжений, трех продолжений, если точно. Реализация доступна в исходниках. Можно поизучать.

Используется много где, да в том же популярном ныне «реактивном функциональном программировании». Хорошо сочетается с событиями (Event и монада Observable).

Можно просто на событие повесить обработчик, который вызовется асинхронно по наступлении события. Самое интересное, что код не разбавляется на части, а многое пишется одним блоком. Монадический bind сам сделает необходимые разрывы и переходы, но на уровне реализации. Внешне код будет выглядеть как единое целое, почти как один поток исполнения.

Фактически, на обработчик события вешается продолжение текущего вычисления. Само вычисление на этом заканчивается. При наступлении события продолжение того вычисления запускается дальше. Идея очень простая, но для красивой реализации используется синтаксический сахар для монад. Это если не оговорить о том, что монады и продолжения очень сильно связаны сами по себе.

dave ★★★★★
()
Ответ на: комментарий от dave

>Фактически, на обработчик события вешается продолжение текущего вычисления.

Интересно и то, что если каким-то образом уметь сериализовывать продолжения, то можно легко и непринуждённо делать failover для таких «длинных» операций. Так как при запуске вычисления у нас есть ссылка на продолжение, мы можем сохранить её, например, в некоторую БД (к примеру, распределённое in-memory хранилище). При получении ответа, достать продолжение из БД и выполнить его.

У нас что-то подобное используется в проекте, правда, код вручную в CPS стиле переписан и потому выглядит ужасненько. А вот на нормальном языке всё было бы гораздо веселее.

WFrag ★★★★
()
Ответ на: комментарий от WFrag

Функции по возможности сериализуются в F#. Они часто имеют атрибут Serializable. Но насколько я знаю, это не всегда так. По-моему последовательности могут не сериализовываться. Соответственно, замыкание будет без нужного атрибута.

Я бы не доверил все автоматике. Она не всесильна :)

dave ★★★★★
()

Генераторы в Питоне например.

elverion
()
Ответ на: комментарий от WFrag

Продолжения в Scala сериализуются. На этом принципе построен Swarm, который «follows the maxim „move the computation, not the data“.

Zenom ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.