A korutīns Tas ir līdzīgs pavedienam, tā ir izpildes līnija ar savu kaudzīti, saviem vietējiem mainīgajiem un savu rādītāju norādījumiem, bet ar īpašu īpatnību, ka tā kopīgo globālos mainīgos un jebkuru citu elementu ar citiem korutīniem.
Bet mums ir jāprecizē, ka pastāv atšķirības pavedieni un korutīni, galvenā atšķirība ir tā, ka programma, kas izmanto pavedienus, tos vienlaikus izpilda, korutīni no otras puses, tie ir kopīgi, kur programma, kas izmanto korutīnus, palaiž tikai vienu no tiem, un to apturēšana tiek panākta tikai tad, ja tas ir skaidri pieprasīts.
korutīni Tie ir ārkārtīgi spēcīgi, redzēsim, ko šis jēdziens ietver un kā mēs varam tos izmantot mūsu programmās.
Pamatjēdzieni
Visas funkcijas, kas saistītas ar korutīniem Lua ir atrodami tabulā, kurā ir funkcija izveidot () ļauj mums tos izveidot, tam ir vienkāršs arguments un tā ir funkcija ar kodu, ko korutīns darbinās, kur tā atdeve ir pavediena tipa vērtība, kas apzīmē jauno korutīnu. Pat arguments, lai izveidotu korutīnu, dažreiz ir anonīma funkcija, kā parādīts šajā piemērā:
co = coroutine.create (function () print ("Hello Solvetic") beigas)A korutīns tam var būt četri dažādi stāvokļi:
- apturēta
- steigā
- miris
- normāli
Kad mēs to izveidojam, tas sākas štatā pārtraukta, kas nozīmē, ka korutīns netiek palaists automātiski, kad tas tiek izveidots pirmo reizi. Ar korutīna statusu var iepazīties šādā veidā:
drukāt (coroutine.status (co))Lai varētu palaist mūsu korutīnu, mums ir jāizmanto tikai funkcija kopsavilkums (), tas, ko tā dara iekšēji, ir mainīt statusu no apturēta uz darbību.
coroutine.resume (co)Ja mēs apkoposim visu savu kodu un pievienosim papildu rindiņu, lai pēc tam vaicātu par mūsu korutīna papildu statusu apkopo mēs varam redzēt visus stāvokļus, caur kuriem tas iet:
co = coroutine.create (function () print ("Hello Solvetic") beigas) print (co) print (coroutine.status (co)) coroutine.resume (co) print (coroutine.status (co))Mēs ejam uz savu termināli un izpildām savu piemēru, apskatīsim mūsu programmas izvadi:
lua coroutines1.lua pavediens: 0x210d880 Suspended Hello Solvetic deadKā redzam, pirmais korutīna iespaids ir pavediena vērtība, tad mums ir stāvoklis apturēta, un tas ir labi, jo šis ir pirmais stāvoklis, veidojot, tad ar apkopo Mēs izpildām korutīnu, ar kuru tas izdrukā ziņojumu, un pēc tam tā statuss ir mirisjo tas pildīja savu misiju.
Korutīni no pirmā acu uzmetiena var šķist sarežģīts funkciju izsaukšanas veids, tomēr tie ir daudz sarežģītāki. To pašu spēks ir lielā daļā funkcijas raža () kas ļauj apturēt darbojošos korutīnu, lai vēlāk atsāktu tā darbību, aplūkosim šīs funkcijas izmantošanas piemēru:
co = coroutine.create (function () for i = 1.10 do print ("apkopojošs korutīns", i) coroutine.yield () beigu gals) coroutine.resume (co) coroutine.resume (co) coroutine.resume (co) coroutine .atsākt (co)Šī funkcija darbosies līdz pirmajai raža, un neatkarīgi no tā, vai mums ir cikls priekš, tas tiks drukāts tikai saskaņā ar tik daudziem apkopo Ļaujiet mūsu korutīnam, lai pabeigtu, redzēsim izvadi caur termināli:
lua coroutines 1. lua 1 2 3 4Tā būtu izeja caur termināli.
Filtri
Viens no spilgtākajiem piemēriem, kas izskaidro korutīnus, ir gadījums patērētājs Y ģenerators informāciju. Pieņemsim, ka mums ir funkcija, kas nepārtraukti ģenerē dažas vērtības, lasot failu, un tad mums ir cita funkcija, kas tās lasa, apskatīsim ilustratīvu piemēru tam, kā šīs funkcijas varētu izskatīties:
funkciju ģenerators (), kamēr taisnība, veic vietējo x = io.read () nosūta (x) beigu beigu funkciju patērētāju (), bet patieso dara vietējais x = saņem () io.write (x, "\ n") beigasŠajā piemērā gan patērētājs, gan ģenerators darbojas bez jebkāda atpūtas, un mēs varam tos apturēt, kad vairs nav apstrādājamās informācijas, tomēr problēma ir šeit, kā sinhronizēt Sūtīt () Y saņemt (), jo katram no tiem ir sava cilpa, un otrs tiek uzskatīts par izsaucamu pakalpojumu.
Bet ar korutīniem šo problēmu var ātri un viegli atrisināt, izmantojot dubultfunkciju atsākt / dot mēs varam panākt, lai mūsu funkcijas darbotos bez problēmām. Kad korutīns izsauc šo funkciju raža, tas neievada jaunu funkciju, bet atgriež zvanu, kas tiek gaidīts un kuru var iziet tikai, izmantojot atsākšanu.
Līdzīgi zvanot apkopo arī nesāk jaunu funkciju, tas atgriež gaidīšanas zvanu raža, apkopojot šo procesu, mums ir jāsinhronizē funkcijas Sūtīt () Y saņemt (). Piemērojot šo darbību, mums tas būtu jāizmanto saņemt () Piesakies apkopo ģeneratoram, lai ģenerētu jaunu informāciju, un pēc tam Sūtīt () pieteikties raža Patērētājam redzēsim, kā mūsu funkcijas izskatās ar jaunajām izmaiņām:
funkcija saņem () vietējais statuss, vērtība = korutīns.atsākt (ģenerators) atgriezt vērtību beigu funkcija sūtīt (x) korutīns.raža (x) beigas gen = korutīns.izveidot (funkcija (), kamēr taisnība darīt lokāli x = io.read () nosūtīt (x) beigas)Bet mēs joprojām varam uzlabot savu programmu, un tas ir, izmantojot filtri, kas ir uzdevumi, kas vienlaikus darbojas kā ģeneratori un patērētāji, veicot ļoti interesantu informācijas pārveidošanas procesu.
A filtrs var darīt apkopo no ģeneratora, lai iegūtu jaunas vērtības un pēc tam piemērotu raža pārveidot datus patērētājam. Apskatīsim, kā mēs varam viegli pievienot filtrus mūsu iepriekšējam piemēram:
gēns = ģenerators () fil = filtrs (gēns) patērētājs (fil)Kā redzam, tas bija ārkārtīgi vienkārši, kur papildus programmas optimizēšanai mēs ieguvām punktus lasāmībā, kas ir svarīgi turpmākajai apkopei.
Korroutīni kā atkārtotāji
Viens no spilgtākajiem ģeneratora / patērētāja piemēriem ir iteratori rekursīvos ciklos, kur iterators ģenerē informāciju, ko organisms patērēs rekursīvā cikla ietvaros, tāpēc nebūtu saprātīgi izmantot korutīnus šo atkārtotāju rakstīšanai, pat korutīniem ir īpašs rīks šim uzdevumam.
Lai ilustrētu izmantošanu, ko mēs varam izmantot korutīni, mēs uzrakstīsim iteratoru, lai ģenerētu dotā masīva permutācijas, tas ir, novietotu katru masīva elementu pēdējā pozīcijā un apgrieztu to, un pēc tam rekursīvi ģenerētu visas atlikušo elementu permutācijas. sākotnējā funkcija būtu bez korutīnām:
funkcija print_result (var) i = 1, #var do io.write (var [i], "") beigas io.write ("\ n") beigasTagad mēs pilnībā mainām šo procesu, vispirms mēs mainām print_result () pēc ražas, redzēsim izmaiņas:
funkcija permgen (var1, var2) var2 = var2 vai # var1, ja var2 <= 1, tad coroutine.yield (var1) elseTomēr tas ir ilustratīvs piemērs, lai parādītu, kā darbojas iteratori Lua nodrošina mums funkciju ar nosaukumu ietīt kas ir līdzīgs izveidotTomēr tas neatgriež korutīnu, tas atgriež funkciju, kas pēc izsaukšanas apkopo korutīnu. Pēc tam izmantot ietīt mums vajadzētu izmantot tikai sekojošo:
funkcija permutācijas (var) atgriež coroutine.wrap (funkcija () permgen (var) beigas) beigasParasti šo funkciju ir daudz vieglāk izmantot nekā izveidot, jo tas dod mums tieši to, kas mums nepieciešams, tas ir, to apkopot, tomēr tas ir mazāk elastīgs, jo tas neļauj mums pārbaudīt ar ietīt.
Korutīni iekšā Lua Tie ir ārkārtīgi spēcīgs rīks, lai tiktu galā ar visu, kas saistīts ar procesiem, kuri jāpilda roku rokā, bet, gaidot informācijas sniedzēja pabeigšanu, mēs varētu arī redzēt, kā tie tiek izmantoti, lai atrisinātu sarežģītas problēmas saistībā ar ģeneratora / patērētāja procesiem kā arī optimizēt iteratoru veidošanu mūsu programmās.