Chyby v korutinách

Co se stane, když se uvnitř korutiny něco pokazí? Druhý den má Hugo na své trase potíže:

-- Hugo ztratil mapu
local hugo = coroutine.create(function()
    coroutine.yield("trh")
    error("Hugo ztratil mapu")
    coroutine.yield("farma")
end)

print(coroutine.resume(hugo))
print(coroutine.resume(hugo))
print(coroutine.status(hugo))
print(coroutine.resume(hugo))
print("Den pokračuje.")

Vypíše:

true	trh
false	main.lua:4: Hugo ztratil mapu
dead
false	cannot resume dead coroutine
Den pokračuje.

Chyba uvnitř korutiny nezastaví program, jen korutinu. Ta je od té chvíle dead (na farmu už se nedostane) a resume vrátí false a chybovou hlášku, přesně jako pcall. Ani spuštění mrtvé korutiny není chyba: dostanete false a cannot resume dead coroutine („nelze pokračovat v mrtvé korutině“).

To se hodí, protože jedna rozbitá postava nezastaví celou hru. Je to ale i past: když se nepodíváte, co resume vrátilo, chyba zmizí beze stopy a korutina prostě potichu přestane cokoli dělat. Když se tedy v korutině něco nestane, vypište si, co vrací resume. V hotovém programu kontrolujte první hodnotu: po local ok, hlaska = coroutine.resume(hugo) je ok rovno false, když se něco pokazilo, a hlaska říká co.

Generátor je jiný. Funkce z coroutine.wrap nevrací true ani false, a proto chybu pošle dál a program skončí jako u každé jiné chyby:

-- Hugo zase ztratil mapu
local dalsiZastavka = coroutine.wrap(function()
    coroutine.yield("trh")
    error("Hugo ztratil mapu")
end)

print(dalsiZastavka())
print(dalsiZastavka())
print("Tenhle řádek se nikdy nespustí.")

Vypíše:

trh
main.lua:8: main.lua:4: Hugo ztratil mapu

Hláška má dvě čísla řádků: main.lua:8: je místo, kde byl generátor zavolán, a main.lua:4: místo, kde uvnitř něj chyba nastala. Spotřebovaný generátor zastaví program stejně, chybou cannot resume dead coroutine. Pokud potřebujete chybu z generátoru zachytit, zavolejte ho pomocí pcall, jako každou jinou funkci: local ok, zastavka = pcall(dalsiZastavka).

Ještě jednu chybu už z této lekce znáte: coroutine.yield() mimo korutinu, třeba ve funkci, kterou jste zavolali přímo, skončí hláškou attempt to yield from outside a coroutine.

Pokyny

Hugo si každý den koupí dýni za 20 mincí. Spusťte program: 3. a 4. den vypíše nesmysl, protože v mince je v tyto dny chybová hláška, a ne číslo. (error(…, 0) vynechá číslo řádku, jak víte z lekce o funkcích.) Kontrolujte ok: když je false, vypište místo toho den a hlášku, třeba Den 3: Hugovi zbylo jen 10 mincí. Program vypíše:

Den 1: Hugo má 30 mincí
Den 2: Hugo má 10 mincí
Den 3: Hugovi zbylo jen 10 mincí
Den 4: cannot resume dead coroutine

Spouštět mrtvou korutinu nemá smysl. Na začátku každého dne zkontrolujte Hugův stav: když je dead, vypište místo spuštění den a Hugo odešel domů. Program vypíše:

Den 1: Hugo má 30 mincí
Den 2: Hugo má 10 mincí
Den 3: Hugovi zbylo jen 10 mincí
Den 4: Hugo odešel domů.

Začněte programovat zdarma

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

Nebo se registrujte pomocí:

5/6