Pull to refresh

Comments 22

Если посмотреть на coroutines in pure java, то он больше похож на то что я обозвал DummySequence, разработчик должен сам явно обособлять каждое состояние из конечного автомата в отедльный шаг. Не думаю, что это удобно.
То что сделал я, гораздо больше похоже на ea-async, но у них нет поддержки yield. Зато их решение production-ready.

Спасибо за статью! На мой взгляд, покрыто более-менее все однопоточное — continuation, state-machine, spilling-unspilling локальных переменных. Осталось только покрыть ContinuationInterceptor и вся магия котлиновских корутин развеется.


Хорошего описания принципа работы котлиновских корутин я не видел.

Видели ли вы мою лекцию по котлиновским корутинам, которую я читал на Физтехе: https://www.youtube.com/watch?v=UzzH4biTEbY?

Лекцию не видел, посмотрю, спасибо!

покрыто более-менее все однопоточное
Многопоточное будет во второй части, но в либе все уже есть, в некотором жизнеспособном виде.
У нас получилась state machine (конечный автомат), и по большому счету именно это делает котлин в своих корутинах (можете декомпилировать и посмотреть, если, конечно, что-нибудь поймете).
Спасибо, ради этого я и продирался через половину статьи. Всё оказывается не так сложно. Выбрали путь скрытого глубокого препроцессинга с преобразованием синтаксиса.
Да другого пути особо и не было, ведь котлин запускается в jvm, в котором нет континуаций. А вот project loom пошел по пути пропатчить рантайм, но там все намного сложнее.
Спасибо, сам хотел писать что-то вроде, но теперь не буду, потому что ваша статья гораздо лучше :) Сам я копался в теме, но разобрался примерно на 1/3 от того, что у у вас написано. Пытаясь понять дзен континуаций (а для этого реализовать их на том языке, что имеется) я дошел примерно до того места, где у вас в статье находится IntegerSequenceContinuation. То есть управляющая конструкция у меня выглядела примерно как
if (step.equals(^_^quotquot^_^) {
...
}
else if (step.equals(^_^quotquot^_^) {
...
}
//todo: сделать по-нормальному, а пока добавлять шагов столько, сколько надо

, а то, что играло роль переменных стэка, я сохранял вообще в БД. Ну, чисто ради proof of concept.

До нормальной технической реализации (генерация байт-кода это для меня черная магия) я не дошел, но слова «multiple stacks» и «континуации позволяют писать асинхронный код как синхронный» стали менее загадочными.

Честно говоря, не знаю, хорошо или плохо, что технология вырулила на этот путь, где мы сейчас находимся (React, Angular, JSON, shadow DOM, change detection, вот это вот все). Как разработчику мне ясно, что синхронный код писать значительно проще, чем асинхронный («реактивный»). В альтернативной истории мы, может быть, разрабатывали бы сейчас веб-приложения на чем-то вроде Seaside, где континуации встроены были с самого начала. Или вообще на каком-нибудь LISP-фреймворке с call/cc.
Встретилось знакомое слово — автомат… А это то, что я просто обожаю. Ниже код так, как я писал бы, пишу (прошу прощения на С++) и использую автоматы. И только, написав свой код, прочитав статью, я только утвердился в мысли, что другие языки меня, думаю, еще долго не будут интересовать (в практическом смысле). Уже за это спасибо. А то, когда читаешь… котлин, роутины и т.д. и т.д. чувствуешь себя несколько, что там скрывать,… отсталым и несколько туповатым. Хотя, не исключаю, что, возможно, так оно и есть (это я так, похоже, комплексую из-за С++?)…
А теперь буквально пару слов по делу. Только написав аналог, я понял сколько и какие можно задать вопросы по поводу подобной «роутины». И их довольно много. Но если в рамках моего кода, который их содержит (как и исходный код), я знаю ответы, то про исходный код?.. То, что на С++ для меня очевидно, тривиально, подобные «облегченные потоки» — это какой-то «вынос мозга»… И как мне после этого бросать С++?
Код автоматов на С++
LArc TBL_gen[] {
	LArc(^_^quotquot^_^, ^_^quotquot^_^, "--", "y1"),
	LArc(^_^quotquot^_^, ^_^quotquot^_^, "--", "y2"),
	LArc(^_^quotquot^_^, ^_^quotquot^_^, "--", "y2"),
	LArc()
}
class generator(): public LFsaAppl
{
public:
	generator():LFsaAppl(TBL_gen) {}
	int k;
	void y1() { k = 10; }
	void y2() { k +=10; }
}

LArc TBL_for[] {
	LArc("f", "f", "^x1", "y1"),
	LArc()
}
class ForFor(): public LFsaAppl
{
public:
	generator *gen;
	ForFor():LfsAppl(TBL_for) {}
	int x1() { return gen->FGetState() == ^_^quotquot^_^; }
	void y1() { print (gen->i); }
}


Можете кидать в меня «какашками», но я не столько для критики написанного, а больше о том, что где-то есть и другая жизнь… С другими автоматами… На «каменно-топорном» С++…

Когда будете переползать на C++20 и попытаетесь понять, как работают горрутины, вспомните эту статью.

Зачем же так путать и пугать мудреными словечками… Нет, чтобы написать просто и по-русски...:( Все же, почувствовав подвох, я набрал в поиске «сопрограммы и корутины». Сразу же вышел на статью: Сопрограммы в Python (https://habr.com/ru/post/196918/) и… Им же лет 60 минимум, как о них пошли разговоры! Можно же было, в конце концов, за эти годы придумать что-то и получше?.. Неужели, чтобы понять, что автоматы перекрывают «с головой» сопрограммы и многопоточность, нужно столько бродить «по пустыне» и так и не набрести?
Может, лучше сразу реализовать автоматы? Не пробовали?

С разморозкой. Корутины уже не те, что были 60 лет назад.
Я как-то уже пошутил про те корутины, которые были 60 лет назад: https://youtu.be/UzzH4biTEbY?t=117.


Может, лучше сразу реализовать автоматы? Не пробовали?

Может, сразу писать на ассемблере? Не пробовали? Компилятор, в отличие от человека, более внимателен и всегда правильно расставит переходы между состояниями автомата, даже в случае сложного потока управления. И у меня еще был бы вопрос к читаемости получившегося кода, но я привык читать байткод корутин, который генерируется котлиновским компилятором. Вы, кстати, пытались отлаживать кучу автоматного кода? А это то, что я делаю по работе, когда мне присылают баг с прикрепленной ссылкой на гитхаб. Ибо даже минимизировать код, воспроизводящий баг не так-то просто. Да, я тоже человек и мой код тоже содержит ошибки, но после их исправления я могу быть уверен, что в подобных случаях автоматы, генерируемые компилятором будут валидными. Если бы я писал их руками каждый раз и заставлял бы своих пользователей писать их руками, никто бы не использовал корутины.


И сделайте, пожалуйста, что-то вроде structured concurrency https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/ на голых автоматах. На корутинах же его возможно сделать (пруф: kotlinx.coroutines).

А чем нынешние принципиально отличаются от тех — прошлых. Там были сопрограммы, а ныне — корутины? Названием? Языком? В Вашем видео плохой звук и как-то сложно себя заставить вникнуть, чтобы разобраться в таком, на мой взгляд, весьма тривиальном вопросе — сопрограммы. Можно как-то кратко сформулировать отличие? Принципиальное. Вне привязки к языку.

Когда-то мои автоматы были, действительно, на ассемблере. Точнее интерпретатор автоматов. Сейчас на С++ и, конечно, медленнее, но есть масса других преимуществ. Код теперь понятнее, компактнее, но, главное, скорости — «за глаза». Даже для управления в реальном времени. А язык — не принципиально. Был ассемблер, затем С, а сейчас С++. Последний в сравнении с первым, конечно, лепота. Ну и что. Идея-то что там, что там — одна.

По поводу генерации компиляторами. Автомат я ему не доверю. И не уговаривайте :) Таблицу переходов (ТП) и код действий пишу сам (см. приведенный пример). Компилятор создает только удобную структуру ТП, которую исполняет интерпретатор. Он реализует любой автомат, как отдельный процесс, а любое их множество — как множество параллельных процессов. Валидность, отладка — просто мечта многопоточного программиста! Любую «кучу автоматов» разгребаю легко и просто. Делал это тысячекратно, наверное;)

Что такое «голый автомат»? Голый, возможно, и не сделает, а нормальные автоматы — все что угодно и влет. Только такими автоматами и только этим и занимаюсь. И пока не было проблем. От слова — совсем ;) От сопрограмм отказался еще до заморозки, а многопоточностью не пользуюсь и после оттайки :) Правда, вот пришлось немножко позаниматься и ею. Не все, к сожалению, влезает в один поток. Да и то пока отложил, т.к. не понадобилось что-то…

Код теперь понятнее, компактнее

Вот вы и ответили на свой же вопрос


Может, лучше сразу реализовать автоматы?

Сравните


suspend fun dummy() {}

suspend fun bar() {
    for (i in 1..10) {
        dummy()
    }
}

С получившимся


   @Nullable
   public static final Object dummy(@NotNull Continuation $completion) {
      return Unit.INSTANCE;
   }

   @Nullable
   public static final Object bar(@NotNull Continuation $completion) {
      Object $continuation;
      label35: {
         if ($completion instanceof <undefinedtype>) {
            $continuation = (<undefinedtype>)$completion;
            if ((((<undefinedtype>)$continuation).label & Integer.MIN_VALUE) != 0) {
               ((<undefinedtype>)$continuation).label -= Integer.MIN_VALUE;
               break label35;
            }
         }

         $continuation = new ContinuationImpl($completion) {
            // $FF: synthetic field
            Object result;
            int label;
            int I$0;
            int I$1;

            @Nullable
            public final Object invokeSuspend(@NotNull Object $result) {
               this.result = $result;
               this.label |= Integer.MIN_VALUE;
               return JvmKt.bar(this);
            }
         };
      }

      Object $result = ((<undefinedtype>)$continuation).result;
      Object var5 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
      int i;
      int var2;
      switch(((<undefinedtype>)$continuation).label) {
      case 0:
         ResultKt.throwOnFailure($result);
         i = 1;
         var2 = 10;
         break;
      case 1:
         var2 = ((<undefinedtype>)$continuation).I$1;
         i = ((<undefinedtype>)$continuation).I$0;
         ResultKt.throwOnFailure($result);
         ++i;
         break;
      default:
         throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
      }

      while(i <= var2) {
         ((<undefinedtype>)$continuation).I$0 = i;
         ((<undefinedtype>)$continuation).I$1 = var2;
         ((<undefinedtype>)$continuation).label = 1;
         if (dummy((Continuation)$continuation) == var5) {
            return var5;
         }

         ++i;
      }

      return Unit.INSTANCE;
   }

Что понятнее и компактнее?


Можно как-то кратко сформулировать отличие? Принципиальное. Вне привязки к языку.

Там же большими буквами название статьи: "Design of a Separable Transition-Diagram Compiler". И там как раз дается определение корутин тогдашних. В чем отличие тогдашних корутин от тогдашних сопрограм? Его нет — это два способа назвать одно и то же. Вот оно, определение, кстати:
Modules which communicate with each other according to the following restrictions:
(I) the only communication between modules is in the form of discrete items of information;
(2) the flow of each of these items is along fixed, one-way paths;
(3) the entire program can be laid out so that the input is at the left extreme, the output is at the right extreme, and everywhere in between all information items flowing between modules have a component of motion to the right.
Сравните это с определением современных корутин: suspendable unit of computation.


По поводу генерации компиляторами. Автомат я ему не доверю.

Могу я узнать причину кроме "я не доверяю компиляторам, лучше уж я ручками"?


Он реализует любой автомат, как отдельный процесс.

То есть у вас по сути акторы. Что опять же, не равно корутинам. Отличие от корутин — корутины могут общаться не только методом передачи сообщений.


нормальные автоматы — все что угодно и влет

"Настоящий шотландец такого никогда не сделает", ага. Если вы такое утверждаете (на автоматах можно сделать structured concurrency), то, разумеется, у вас есть пруфы. "Где пруфы, Билли, нам нужны пруфы".


И да, под сообщением есть ссылка "ответить". Не имеет смысла каждый новый ответ писать на верхнем уровне комментариев.

Сравните это с определением современных корутин: suspendable unit of computation.

Прошу прощения, я после заморозки и с английским туговато. Давайте больше на русском общаться. Так избежим толкований и быстрее разберемся. Пока я не уловил не то, что разницы, а даже сходства. Потоки тоже приостанавливаются. Они тоже корутины? Но то, что потоки не сопрограммы это, надеюсь, еще не поменялось?
Могу я узнать причину кроме «я не доверяю компиляторам, лучше уж я ручками»?

Алгоритм (логику его работы) пишет всегда программист. Только поэтому. Конечно, есть методы, например, автоматического распараллеливания, генетические алгоритмы или нейронные сети там или что-то этому подобное, но… все это «от лукавого». Искусственного интеллекта еще нет и будет ли он когда-нибудь? Так что пока автоматы приходится пилить самому :(
То есть у вас по сути акторы.

У меня — автоматы. Точнее автоматные процессы. Т.е. это обычные процессы, в которых вместо модели блок-схем используется модель автомата (таблица переходов автомата). Т.е. вместо if, else и т.п. ТП, как в коде примера. Для описании логики процесса я не использую обычные операторы управления. Состояния КА — это, можно сказать, и есть точки приостанова вычислений, чтобы передать управление другому автомату и т.д.
Общаются между собой автоматы любыми известными способами. Хоть сообщениями, хоть через переменные, могут использовать текущие состояния, глобальные переменные, локальные свойства объектов и т.д. и т.д. Т.е. ограничений на общение нет, все те общения, что доступны в рамках потока (да хоть между потоками), те и могут использоваться.
разумеется, у вас есть пруфы.

Не знаю Не знаком. Может есть. Поясните безграмотному, что такое пуфы.
Более того. Если много автоматов работают параллельно в одном потоке, то и приостановка и возобновление вычислений такое же, как у сопрограмм: выхожу из одной точки и возвращаюсь в ту же. А вот логика (алгоритм) работы процесса представлен автоматом.
PS
Уж коли речь зашла о событиях…
Отличие от корутин — корутины могут общаться не только методом передачи сообщений.

Посмотрите мою статью на хабре, как к подобным вещам отношусь — habr.com/ru/post/483610.

Вот корутины — это то, что вы описали, только генерируется компилятором. Каждое состояние — это либо вызов другой корутины либо явное указание, что здесь можно уснуть и передать управление другой корутине и при каком условии надо эту корутину разбудить.


Плюс корутин, по сравнению с автоматным программированием (термин, который я встречал только в отечественном computer science, на западе такого термина нет. Если и был, то он изжил себя. Там ему и место — на свалке истории) в том, что не надо самостоятельно строить автомат. Это сделает компилятор. Точно так же, как от программ с кучей переходов по меткам перешли на структурное программирование, а переходы теперь расставляет компилятор, так и от ручного построения автоматов в 60-80-х перешли на генерацию автоматов компилятором. И даже этого недостаточно. Structured concurrency (даже не просите перевести, не могу. В русском языке нет аналогичного понятия. И даже термин сопрограммы ужасен с точки зрения семантики, потому что программа все равно одна, чему там "со-". Поэтому я использую кальку "корутины", которую можно перевести как "софункции" или "сопроцедуры") решает те же проблемы, что и структурное программирование решало во времена Дейктры — делает понимание чужого кода более простым. Основная идея в том, что если поток/корутина запускает несколько других потоков/корутин, то он/она должен/должна дождаться их работы. Это очень сильно облегчает параллельное и асинхронное программирование, в частности, упрощает обработку ошибок, так как количество состояний, в котором может пребывать программа, уменьшается.


Сейчас разница между корутиной и потоком становится все более и более размытой. В go, D, raku и в назревающем loom (жалко, что я не пишу этот комментарий по-английски, могла бы быть неплохая игра слов), например, корутины ведут себя практически как потоки. Их становится не отличить. В kotlin, c++20, javascript, C# и rust разница между корутинами и потоками еще остается явной.


Пруф — ссылка на код, который реализует structured concurrency, желательно, неявно. Хотя неявно в автоматном программировании невозможно — это все равно, что программировать на языке ассемблера без макроассемблера, ручками считая адреса переходов.

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

Это в принципе не верно. Есть 1) поток/потоки, которые не являются по определению вычислительными моделями 2) сопрограммы, которые в сравнении с потоками вводят точки приостанова/возобновления вычислений, но тоже не модель вычислений 3) есть блок-схемы/автоматы, которые формируют вычислительную модель.
Как может «размываться» то, что в принципе не смешивается. В данном случае (3) используется для реализации (1) и (2). Из этого и надо строго исходить. Могут быть разные подходы к реализации, порождающие тот или иной язык, то это только так — автоматы (речь о них) реализуют потоки, автоматы реализуют сопрограммы, но никак наоборот. Это азы теории. Если рассуждать по-другом, то и будет та самая «размытая каша».
Вы упомянули параллельное и асинхронное программирование, которое что-то там облегчает реализовать. Те же «корутины». Чтобы понять, как они это делают, нужны формулировки понятий параллельного и асинхронного программирования. А есть еще и синхронное программирование. Чем оно отличается от упомянутых двух? (Нет параллельного И асинхронного программирования. Есть параллельное программирование, которое может быть асинхронным или синхронным). И какая здесь роль «корутин». Понятно как создать любую параллельную модель (синхронную, асинхронную и т.п.) с помощью автоматов. Но ни потоки, ни сопрограммы не являются вычислительными моделями. Они вводят лишь некую структурную организацию в вычисления. И не более того. С их помощью ничего нельзя вычислить. Вычисления создает блок-схемная модель (автоматы Вы не используете), которую вы и «размываете» между потоками и сопрограммами. Вот «на пальцах» процесс работы всего это «серпентария». Все остальная «реализация» — от лукавого. Под капотом может быть все что угодно. Чтобы отделить «мух от котлет» нужно именно этим и руководствоваться, а не смешивать все в одну кучу.
Там ему и место — на свалке истории
«Этого не может быть потому, что этого быть не может». Просто потому, что его «история» только начинается. Это UML, это Stateflow в MATLAB. И то это только-только начало. Не спешите «выплескивать» то, что еще только нарождается.
И давайте меньше оглядываться на «запад», а больше работать своей головой, создавая адекватные, понятные русскоязычные понятия. А то все эти «пруфы», «корутины» и т.п. только мешают понять смысл обсуждаемого да и как-то смешно звучат (какие-то песенки Винни-Пруфа).
Это в принципе не верно.

Назовите хотя бы одну ОС, в которой потоки/треды реализованы не через приостановку вычислений вне зависимости от того, что этот поток сейчас делает. Где здесь автомат? ОС может остановить поток в (теоретически) любой ассемблерной инструкции. Или вы каждую инструкцию собираетесь сделать состоянием в автомате?


Есть параллельное программирование, которое может быть асинхронным или синхронным

А как быть с однопоточной асинхронной моделью (как вы могли про нее не слышать? В каком манямирке вы живете?). И, разумеется, многопоточный != параллельный. Вот хорошее объяснение: https://codewala.net/2015/07/29/concurrency-vs-multi-threading-vs-asynchronous-programming-explained/.


Вычисления создает блок-схемная модель

Да хоть Господь Бог. Это не имеет значения ни для потоков, ни для корутин. Почти любой код можно преобразовать в приостанавливаемый. Посмотрите, как те же корутины реализованы в go. В kotlin они реализованы с явными точками останова, но это особенности реализации, иначе было сделать нельзя. В go же таких проблем нет и там нет явных точек останова, совсем как в потоках. Где, черт возьми, здесь автоматы?


И давайте меньше оглядываться на «запад»,

А давайте вы не будете разглагольствовать с умным видом о том, в чем очевидно не разбираетесь. У меня еще была надежда, что вы просто ни разу не программировали на языке с корутинами, но эта надежда уже развеялась после "автоматы реализуют потоки, автоматы реализуют сопрограммы". Это уже давно не так, и, скорее всего, лет как минимум 40 не так. Те же потоки линукса как пруф (возьмите любой словарь английского, хоть 50-го года издания и посмотрите значение слова proof).


Это азы теории.

Когда теория расходится с наблюдениями, теорию принято дополнять, а не игнорировать наблюдения. Это азы эпистомологии.


больше работать своей головой

Я за. Только когда это работает в обе стороны. Давайте вы сначала посмотрите как реализованы корутины хотя бы в двух языках, скажем, в kotlin и go, а также как реализованы потоки в линуксе, найдете 10 отличий корутин в go от потоков в линуксе, потом мы возобновим беседу, иначе это разговор немого с незнающим.


И да, я не могу игнорировать "запад", я живу на "западе". И я все еще не увидел реализации structured concurrency на автоматах. Ответы без ссылки на реализацию я буду впредь игнорировать. Не вижу смысла спорить без железных аргументов, ваши "верю-не верю, ибо это, мой взгляд, азы" за железные аргументы не сойдут.

Назовите хотя бы одну ОС, в которой потоки/треды реализованы...

У Вас перемешаны логическое описание и его реализация. На уровне представления потоки не приостанавливаются нигде. На уровне реализации — везде. Мысль понятна? На уровне логического описания потоки и в Африке потоки. Как они реализованы, что там «под капотом» меня совершенно не интересует. Это дело разработчиков реализовать корректно идею тех же потоков, сопрограмм, корутин, автоматов и далее по списку. Как еще Вам это сказать. Вы тянете меня в реализацию, в разные языки, но мне это «до фонаря», т.к. важно, чтобы рассматриваемая абстракция везде работала одинаково. Еще раз — одинаково. Да, язык ее описания может различаться, но логика работы — нет.
А давайте вы не будете разглагольствовать с умным видом о том, в чем очевидно не разбираетесь. У меня еще была надежда, что вы просто ни разу не программировали на языке с корутинами...

Еще раз и еще раз я использую автоматную модель. Примитивные вещи вроде потоков и корутин мне не нужны ни разу. Ну, совсем. Автоматное программирование все это покрывает, «как бык овцу». Собственно своим приведенным примером я это и показал.
И я все еще не увидел реализации structured concurrency на автоматах.
Когда Вы разберетесь наконец-то с этим понятием и опишите его на великом и могучем, чтобы его можно было трактовать однозначно, то, заверяю Вас, увидите сразу же. Автоматы, как аналог машины Тьюринга, реализует все, что могут придумать и задумать Ваши «западные мозги». Это доказано ими же (мозгами самого Тьюринга). Потоки и корутины не эквивалентны ни какой машине. Поэтому в чистом виде они ограничены по определению. Чтобы что-то сделать осмысленное Вы разбавляете их моделью блок-схем. Вот и все «на пальцах». Как все это реализовано — программно, аппаратно, ездит на бензине, жрет ли солому — без разницы. Главное, чтобы реализовало задуманное на уровне своего представления. И какие при этом будут проблемы — вот, что важно. Как будет реализовано — не важно. Это обязанность разработчика, чтобы все работало одинаково в любой ОС и на любом языке. Причем так, чтобы у меня не было желания лезть под капот. Мне главное доехать. И чтобы машины с точки зрения управления ими были одинаковы. Когда все «размыто», то не ясно чего ожидать от самой продвинутой «машины». Если продолжить ассоциацию, то потоки — машины, которые едут только прямо, корутины — прямо, но приостанавливаясь, и только автоматы имеют полную свободу передвижения (как у товарища Тьюринга).
Поток это последовательность инструкций, которые выполняются друг за другом. Инструкции могут быть как на тьюринг полном языке, так и нет. Утверждение «Потоки эквивалентны (не эквиваленты) машине Тьюринга» не несет смысла. Это как сравнивать кислое и квадратное.
Это как сравнивать кислое и квадратное.

Вы правы. Сравнивать несравнимое лучше не надо. Но тут вынужденно ;) Только я бы сказал так — дорогу и машину. Или дорогу с пробками и машину, если речь про «корутины». А вот автоматы и есть та самая машина, а множество автоматов — множество машин ;)
Кстати… Что-то в коде моего примера первая ТП совсем извратилась (имена состояний). И как поправить — не знаю :( Но вторая таблица переходов отобразилась нормально. Похоже, имена состояний в виде цифр воспринимаются как-то своеобразно. Знал бы — использовал буковки ;)
Заинтересовала реклама книги на Хабре: C++. Практика многопоточного программирования. habr.com/ru/company/piter/blog/484818. Хотел прикупить хотя бы электронный вариант. Но перед этим в инете нашел предыдущее издание — 2012 года. В новом, похоже, термин «параллелизм» заменили на «конкурентность», а «многопоточнось» на «параллелизм». Желание резко улетучилось. А все от того, что кое-кто берется за переводы, не разобравшись в смысле того, что переводит. Все это напомнило наши «терминологические споры»… «Конкурентный корутинизм» какой-то…
И еще. Ни в одном из изданий (в первом так точно) ни про корутины, ни про сопрограммы нет ни слова. Поэтому, предлагая реализацию «корутин», нужно привести более весомые аргументы в пользу необходимости заниматься ими. Т.к. по словам одних корутины «размываются» с потоками, т.е. мигрируют в их сторону, а те, кто рассматривает потоки, похоже, корутины игнорируют напрочь.
Может лучше потратить силы на реализацию чего-то более полезного и понятного?
Sign up to leave a comment.