LOGOFALPROG Telegram 178
Но, по правде говоря, прямо функции и классы в терминах конкретного языка виртуальная машина вам генерить не обязана, потому что они наружу не видны, но по смыслу там ровно это происходит. Но вот эта простая смена формы записи и есть та самая ментальная ступенька, о которой я говорил в начале, так как она сильнейшим образом развязывает руки и мозги геймплейному программисту в плане стейт-машин.

Но погодите. Генераторы это ещё не корутины. Код с yield-ами, что я показал выше, в такой форме использовать вообще-то не получится. Дело в том, что внутри указанных функций есть вложенные yield-ы. Поэтому в вызывающем коде придётся крутить циклы. Либо же возвращать вложенный генератор и написать обёртку, которая будет складировать генераторы в стек и разруливать их вызовы соответствующим образом. Это пишется очень легко и так сделаны, например, всем известные Unity-корутины. И вот это уже тянет на некое подобие нормальных асимметричных корутин.

«Асимметричных», потому что стек выстраивает отношения между генераторами по принципу «вызывающий-вызываемый». Но в принципе можно переключаться между генераторами не по логике стека, а как взбредёт в голову. И тогда такие корутины будут называться «симметричными». В том смысле, что отношения между ними симметричные, то есть все на равных правах. Так можно, например, завести параллельные функции, которые передают друг другу управление по принципу пинг-понга. Но это мы опять же уходим в сторону многопоточных историй, а в нашем спокойном и безопасном однопоточном месте такие выкрутасы не особо нужны. Вернёмся к нашим тотемным животным.

У нас всё ещё не полноценные корутины, а симулякр. Если мы захотим сделать yield где-то далеко на глубине стека вызовов в C#, нам хоть и не придётся теперь крутить цикл в каждом месте, но протаскивать yield всё же придётся через все уровни. Если бы корутины были реализованы на уровне языка, как, например, в Kotlin, то мы могли бы ещё немного улучшить жизнь нашим сурикатам, прокидывая yield с любой глубины. Это намного удобнее. Но не идеально, потому что в Kotlin все промежуточные функции придётся пометить как suspend. Тогда компилятор будет обращаться с этими функциями, как с генераторами (для их промежуточного состояния будет создаваться объект), но эти функции тогда будет нельзя вызывать из non-suspend функций. То есть помечая функцию как suspend, мы рискуем, что часть старого кода отвалится.

— А бывают ли вообще идеальные корутины? — спросите вы. — Чтобы вызываться без боли из любого места и не думать о том, какая там была функция.

Да, бывают. Мы наконец-то пришли к stack-full корутинам. Это когда вместо вот этой всей пурги про разрезание функций на много маленьких и создание структурок-состояний, мы просто берём и сохраняем целиком весь стек приложения. Сохраняем со всеми его обычными и волшебными функциями вообще без ограничений.

Я встречал stack-full корутины как минимум 2 раза. Этол boost-овые в С++. Но сами понимаете: С++ сам по себе такой, что «без боли» к нему слабоприменимое понятие. И, конечно же, в Lua. Это мои первые и самые любимые корутины, потому что корутины там, как говорится, first-class-citizen: они yield-ятся в любой момент и с любого уровня, не требуют менять существующий код и никак не мешают вызывать эти же функции вне корутин — одно удовольствие. Идеально для написания толп сурикат.

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

Надеюсь, я развеял этот миф и эта статья открыла для кого-то корутины по-новому. Ну или по крайней мере стал сам лучше понимать эту область.



tgoop.com/logofalprog/178
Create:
Last Update:

Но, по правде говоря, прямо функции и классы в терминах конкретного языка виртуальная машина вам генерить не обязана, потому что они наружу не видны, но по смыслу там ровно это происходит. Но вот эта простая смена формы записи и есть та самая ментальная ступенька, о которой я говорил в начале, так как она сильнейшим образом развязывает руки и мозги геймплейному программисту в плане стейт-машин.

Но погодите. Генераторы это ещё не корутины. Код с yield-ами, что я показал выше, в такой форме использовать вообще-то не получится. Дело в том, что внутри указанных функций есть вложенные yield-ы. Поэтому в вызывающем коде придётся крутить циклы. Либо же возвращать вложенный генератор и написать обёртку, которая будет складировать генераторы в стек и разруливать их вызовы соответствующим образом. Это пишется очень легко и так сделаны, например, всем известные Unity-корутины. И вот это уже тянет на некое подобие нормальных асимметричных корутин.

«Асимметричных», потому что стек выстраивает отношения между генераторами по принципу «вызывающий-вызываемый». Но в принципе можно переключаться между генераторами не по логике стека, а как взбредёт в голову. И тогда такие корутины будут называться «симметричными». В том смысле, что отношения между ними симметричные, то есть все на равных правах. Так можно, например, завести параллельные функции, которые передают друг другу управление по принципу пинг-понга. Но это мы опять же уходим в сторону многопоточных историй, а в нашем спокойном и безопасном однопоточном месте такие выкрутасы не особо нужны. Вернёмся к нашим тотемным животным.

У нас всё ещё не полноценные корутины, а симулякр. Если мы захотим сделать yield где-то далеко на глубине стека вызовов в C#, нам хоть и не придётся теперь крутить цикл в каждом месте, но протаскивать yield всё же придётся через все уровни. Если бы корутины были реализованы на уровне языка, как, например, в Kotlin, то мы могли бы ещё немного улучшить жизнь нашим сурикатам, прокидывая yield с любой глубины. Это намного удобнее. Но не идеально, потому что в Kotlin все промежуточные функции придётся пометить как suspend. Тогда компилятор будет обращаться с этими функциями, как с генераторами (для их промежуточного состояния будет создаваться объект), но эти функции тогда будет нельзя вызывать из non-suspend функций. То есть помечая функцию как suspend, мы рискуем, что часть старого кода отвалится.

— А бывают ли вообще идеальные корутины? — спросите вы. — Чтобы вызываться без боли из любого места и не думать о том, какая там была функция.

Да, бывают. Мы наконец-то пришли к stack-full корутинам. Это когда вместо вот этой всей пурги про разрезание функций на много маленьких и создание структурок-состояний, мы просто берём и сохраняем целиком весь стек приложения. Сохраняем со всеми его обычными и волшебными функциями вообще без ограничений.

Я встречал stack-full корутины как минимум 2 раза. Этол boost-овые в С++. Но сами понимаете: С++ сам по себе такой, что «без боли» к нему слабоприменимое понятие. И, конечно же, в Lua. Это мои первые и самые любимые корутины, потому что корутины там, как говорится, first-class-citizen: они yield-ятся в любой момент и с любого уровня, не требуют менять существующий код и никак не мешают вызывать эти же функции вне корутин — одно удовольствие. Идеально для написания толп сурикат.

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

Надеюсь, я развеял этот миф и эта статья открыла для кого-то корутины по-новому. Ну или по крайней мере стал сам лучше понимать эту область.

BY Log of Alprog


Share with your friend now:
tgoop.com/logofalprog/178

View MORE
Open in Telegram


Telegram News

Date: |

Ng, who had pleaded not guilty to all charges, had been detained for more than 20 months. His channel was said to have contained around 120 messages and photos that incited others to vandalise pro-government shops and commit criminal damage targeting police stations. Just as the Bitcoin turmoil continues, crypto traders have taken to Telegram to voice their feelings. Crypto investors can reduce their anxiety about losses by joining the “Bear Market Screaming Therapy Group” on Telegram. Healing through screaming therapy The administrator of a telegram group, "Suck Channel," was sentenced to six years and six months in prison for seven counts of incitement yesterday. fire bomb molotov November 18 Dylan Hollingsworth yau ma tei
from us


Telegram Log of Alprog
FROM American