Pozastavení funkce

Vítejte v lekci o korutinách, poslední velké části jazyka Lua. Mnoho začátečníků se s ničím podobným ještě nesetkalo, a proto nezačneme kódem, ale nápadem.

Každá funkce, kterou jste zatím napsali, proběhne od začátku do konce najednou: když ji zavoláte, zbytek programu čeká, dokud neskončí. Teď si představte, že vám Ema vypráví o svém dni kousek po kousku. Ráno řekne: „Nakrmila jsem slepice.“ Pak jde po své práci. Když ji potkáte v poledne, nezačne znovu od začátku, ale pokračuje: „Zalila jsem mrkev.“ Pamatuje si, kde přestala.

Korutina je funkce, která umí totéž: zastavit se uprostřed, zapamatovat si, kde byla (i hodnoty svých lokálních proměnných), a později pokračovat přesně od toho místa. Název pochází z anglického coroutine: „routine“ je staré slovo pro funkci a předpona „co-“ znamená „spolu“, protože korutina se střídá se zbytkem programu. Takhle vypadá Emin den jako korutina:

-- Emin den krok za krokem
local function eminDen()
    print("Ema krmí slepice.")
    coroutine.yield()
    print("Ema zalévá mrkev.")
    coroutine.yield()
    print("Ema prodává vejce na trhu.")
end

local den = coroutine.create(eminDen)
print(coroutine.status(den))
coroutine.resume(den)
print("(Slunce stoupá výš.)")
coroutine.resume(den)
print(coroutine.status(den))
coroutine.resume(den)
print(coroutine.status(den))

Vypíše:

suspended
Ema krmí slepice.
(Slunce stoupá výš.)
Ema zalévá mrkev.
suspended
Ema prodává vejce na trhu.
dead

Práci obstarají tři funkce z knihovny coroutine:

  • coroutine.create(eminDen) vytvoří z funkce eminDen korutinu. Zatím z ní nic nespustí. Předáváte samotnou funkci, bez závorek.
  • coroutine.resume(den) spustí korutinu a nechá ji běžet, dokud nedojde ke coroutine.yield() nebo na konec funkce. První resume začne na začátku funkce, každé další pokračuje hned za tím yield, kde se korutina zastavila. (Resume znamená „pokračovat“.)
  • coroutine.yield() uvnitř funkce korutinu pozastaví a program pokračuje za tím resume, které ji spustilo. (Yield znamená „dát přednost“, jako auto na křižovatce.)

coroutine.status(den) řekne, v jakém stavu korutina je: suspended (pozastavená: ještě nezačala, nebo čeká u yield), running (její kód právě běží, takže tohle může zjistit jen korutina sama o sobě) nebo dead (doběhla na konec své funkce a už pokračovat nemůže; doslova „mrtvá“).

K čemu to je? Hry jsou plné věcí, které chvíli trvají: obchodník Hugo cestuje od města k městu, dveře se pomalu otevírají, Ema přechází přes pole. Hra kreslí nový obrázek (snímek, anglicky frame) mnohokrát za sekundu, nebo v tahové hře dává tah každé postavě, a všechny tyhle věci musí postupovat po malých krocích. S korutinou napíšete takovou věc jako jednu obyčejnou funkci od začátku do konce a coroutine.yield() dáte všude, kde má počkat na další snímek nebo tah. Takové scénáře budete psát později v této lekci.

Časté chyby:

  • Zavolat funkci sami, eminDen(), nebo se závorkami v coroutine.create(eminDen()). V obou případech poběží eminDen jako obyčejná funkce, ne jako korutina, a její yield nemá co pozastavit. Program vypíše Ema krmí slepice. a skončí chybou attempt to yield from outside a coroutine („pokus o yield mimo korutinu“). Tahle hláška nemá číslo řádku; řádek najdete ve stack traceback: pod ní.
  • Zavolat korutinu jako funkci, den(). Korutina není funkce, je to hodnota vlastního typu thread, a proto dostanete attempt to call a thread value (local 'den'). Korutina se spouští jen přes coroutine.resume.

Pokyny

Ema zalévá pole, ale po prvním záhonu si chce odpočinout. Udělejte z funkce zalijPole korutinu: za zalití záhonu 1 a za zalití záhonu 2 (za záhon 3 už ne) dejte coroutine.yield(). Volání zalijPole() nahraďte řádkem local zalevani = coroutine.create(zalijPole), korutinu zalevani jednou spusťte pomocí resume a pak vypište Ema si dává přestávku. Program vypíše:

Záhon 1 je zalitý
Ema si dává přestávku.

Po přestávce vypište stav korutiny za textem Stav: . Pak korutinu zalevani ještě dvakrát spusťte pomocí resume a vypište její stav znovu. Program vypíše:

Záhon 1 je zalitý
Ema si dává přestávku.
Stav: suspended
Záhon 2 je zalitý
Záhon 3 je zalitý
Stav: dead

Začněte programovat zdarma

Registrací souhlasíte s provozními podmínkami a zásadami ochrany osobních údajů.

Nebo se registrujte pomocí:

1/6