Цорроутинес ин Луа

А. цороутине Сличан је нити, то је линија за извршавање са сопственим стеком, сопственим локалним променљивим и сопственим показивачем за упутства, али са посебношћу да дели глобалне променљиве и било који други елемент са осталим корутинама.

Али морамо разјаснити да постоје разлике између нити и корутине, главна разлика је у томе што програм који користи нити покреће ове паралелно, корутине с друге стране, они су колаборативни, где програм који користи супрограме покреће само једну од ових, а обустава ових се постиже само ако се то изричито захтева.

Тхе корутине Изузетно су моћни, хајде да видимо шта овај концепт обухвата и како их можемо користити у нашим програмима.

Основни појмови


Све функције повезане са супрограмима у Луа налазе се у табели супрограма, где је функција Креирај () дозвољава нам да их креирамо, има једноставан аргумент и функција је са кодом који ће покренути супрограм, где је њен повратак вредност типа нити, која представља нову супрограму. Чак је и аргумент за стварање супрограма понекад анонимна функција као у следећем примеру:
 цо = цороутине.цреате (фунцтион () принт ("Хелло Солветиц") енд)
А. цороутине може имати четири различита стања:
  • суспендован
  • у журби
  • мртав
  • нормално

Када га створимо, он почиње у стању прекинута, што значи да се супрограм не покреће аутоматски када се први пут креира. Статус корутине се може консултовати на следећи начин:

 принт (цороутине.статус (цо))
Где можемо да покренемо нашу рутину морамо само да користимо функцију резимира (), што интерно ради мења статус са суспендованог на трчање.
 цороутине.ресуме (цо)
Ако саставимо сав наш код и додамо додатни ред за испитивање додатног статуса наше сурутине након тога резимира можемо видети сва стања кроз која пролази:
 цо = цороутине.цреате (фунцтион () принт ("Здраво Солветиц") енд) принт (цо) принт (цороутине.статус (цо)) цороутине.ресуме (цо) принт (цороутине.статус (цо))
Идемо на наш терминал и покрећемо наш пример, да видимо излаз нашег програма:
 луа цороутинес1.луа тхреад: 0к210д880 Суспендед Хелло Солветиц деад
Као што видимо први утисак корутине је вредност нити, онда имамо стање суспендован, и ово је у реду јер је ово прво стање при креирању, а затим са резимира Покрећемо корутину помоћу које штампа поруку и након тога њен статус је мртавпошто је испунила своју мисију.

Програми на први поглед могу изгледати као компликован начин позивања функција, међутим они су много сложенији од тога. Снага истих почива у великом делу функције ииелд () која дозвољава суспендовање супрограма који је покренут да би касније наставила са радом, да видимо пример коришћења ове функције:

 цо = цороутине.цреате (фунцтион () фор и = 1.10 до принт ("суммаризинг цороутине", и) цороутине.ииелд () енд енд) цороутине.ресуме (цо) цороутине.ресуме (цо) цороутине.ресуме (цо) цороутине .ресуме (цо)
Ова функција ће радити до првог принос, и без обзира на то да ли имамо циклус за, штампаће се само према толико резимира Хајде да завршимо са нашом рутином, да завршимо да видимо излаз кроз терминал:
 луа корутине 1. луа 1 2 3 4
Ово би био излаз кроз терминал.

Филтери


Један од најјаснијих примера који објашњавају корутине је случај потрошача И генератор информација. Претпоставимо онда да имамо функцију која континуирано генерише неке вредности читањем датотеке, а затим имамо другу функцију која их чита, да видимо илустративан пример како би ове функције могле изгледати:
 генератор функција () док је труе ради локални к = ио.реад () шаље (к) крај крај функција потрошач () док је тачно ради локални к = прима () ио.врите (к, "\ н") крај крај
У овом примјеру и потрошач и генератор раде без икаквог одмора и можемо их зауставити када нема више информација за обраду, међутим проблем је овдје како синхронизирати функције Пошаљи () И примити (), будући да сваки од њих има своју петљу, а за другу се претпоставља да је услуга коју је могуће позвати.

Али са супрограмима овај проблем се може решити брзо и једноставно, коришћењем двоструке функције животопис / принос можемо учинити да наше функције раде без проблема. Када супрограм позове функцију принос, не улази у нову функцију, већ враћа позив који је на чекању и који из тог стања може изаћи само помоћу наставка.

Слично и приликом позива резимира такође не покреће нову функцију, враћа позив на чекање на принос, резимирајући овај процес треба да синхронизујемо функције Пошаљи () И примити (). Примењујући ову операцију коју бисмо морали да користимо примити () Применити резимира до генератора за генерисање нових информација, а затим Пошаљи () применити принос За потрошаче, да видимо како наше функције изгледају са новим променама:

 функција рецеиве () локални статус, валуе = цороутине.ресуме (генератор) повратна вредност енд фунцтион сенд (к) цороутине.ииелд (к) енд ген = цороутине.цреате (фунцтион () док је труе до лоцал к = ио.реад () сенд (к) енд енд)
Али и даље можемо побољшати наш програм, а то је коришћењем филтери, који су задаци који истовремено функционишу као генератори и потрошачи чинећи веома занимљив процес трансформације информација.

А. филтер могу урадити резимира из генератора да бисте добили нове вредности, а затим примените принос да трансформише податке за потрошача. Хајде да видимо како можемо лако додати филтере у наш претходни пример:

 ген = генератор () фил = филтер (ген) потрошач (фил)
Као што видимо, било је крајње једноставно, где смо поред оптимизације нашег програма стекли бодове у читљивости, важне за будуће одржавање.

Програми као итератори


Један од најјаснијих примера генератора / потрошача је итератори присутни у рекурзивним циклусима, где итератор генерише информације које ће тело потрошити у току рекурзивног циклуса, па не би било неразумно користити супрограме за писање ових итератора, чак и супрограми имају посебан алат за овај задатак.

Да илуструјемо употребу коју можемо имати корутине, написаћемо итератор за генерисање пермутација датог низа, односно, поставити сваки елемент низа на последњу позицију и окренути га, а затим рекурзивно генерисати све пермутације преосталих елемената, да видимо како ће наш оригинална функција би била без укључивања супрограма:

 функција принт_ресулт (вар) за и = 1, #вар до ио.врите (вар [и], "") крај ио.врите ("\ н") крај
Оно што радимо је да потпуно променимо овај процес, прво променимо принт_ресулт () по приносу, да видимо промену:
 функција пермген (вар1, вар2) вар2 = вар2 или # вар1 ако је вар2 <= 1 онда цороутине.ииелд (вар1) елсе
Ово је илустративан пример који показује како итератори раде Луа пружа нам функцију која се назива омотати који је сличан КреирајМеђутим, не враћа супрограм, враћа функцију која, када се позове, резимира супрограм. Затим за употребу омотати требало би да користимо само следеће:
 функција пермутације (вар) повратак цороутине.врап (фунцтион () пермген (вар) крај) крај
Обично је ова функција много лакша за коришћење него Креирај, будући да нам даје управо оно што нам је потребно, што је да резимирамо, међутим, мање је флексибилно јер нам не дозвољава да провјеримо статус супрограма створеног са омотати.

Супрограми у Луа Они су изузетно моћан алат за рјешавање свега у вези с процесима који се морају извести руку под руку, али чекајући завршетак оног ко даје информације, могли смо видјети и њихову употребу за рјешавање сложених проблема у вези са процесима генератора / потрошача а такође и оптимизирање конструкције итератора у нашим програмима.

wave wave wave wave wave