Chyby a pcall
Zatím chyby hlásila sama Lua: volání nil, sčítání s nil… Chyby ale můžou hlásit i vaše funkce. Když funkce dostane hodnoty, se kterými neumí pracovat, je lepší skončit se srozumitelnou hláškou než pokračovat se špatným výsledkem. K tomu slouží error:
local mince = 20
local function kupSemena(cena, balicky)
local naklady = cena * balicky
if naklady > mince then
error("Málo mincí")
end
mince = mince - naklady
return mince
end
print(kupSemena(2, 5))
print(kupSemena(5, 4))
print("Hotovo")Vypíše:
10
main.lua:6: Málo mincí
stack traceback:
[C]: in function 'error'
main.lua:6: in local 'kupSemena'
main.lua:13: in main chunkerror program zastaví, stejně jako chyba, kterou hlásí Lua: Hotovo se už nevypíše. Lua před vaši hlášku přidá main.lua:6:, řádek, na kterém se error zavolal. Traceback ukazuje, jak se tam program dostal. Čtěte ho odspodu: hlavní program na řádku 13 zavolal kupSemena a ta na řádku 6 zavolala error. ([C] znamená funkci zabudovanou do Lua, která je napsaná v jazyce C.) Když pozici ve zprávě nechcete, předejte jako druhý argument 0: error("Málo mincí", 0).
„Když tohle neplatí, skonči chybou“ je tak častá kontrola, že pro ni existuje zkratka: assert(podminka, hlaska). Když podmínka platí, assert nic nedělá. Když je false nebo nil, skončí s danou hláškou:
local function zasej(plodina, zahony)
assert(zahony > 0, "Zasejte aspoň jeden záhon")
print("Zaseto: " .. plodina .. ", záhonů: " .. zahony)
end
zasej("mrkev", 3)
zasej("pšenice", 0)Vypíše:
Zaseto: mrkev, záhonů: 3
main.lua:2: Zasejte aspoň jeden záhonNěkdy by ale chyba neměla ukončit celý program. Ema si nemůže dovolit semena dýně, ale ostatní semena koupit chce. pcall (protected call, chráněné volání) zavolá funkci a zachytí její chybu. Předejte mu funkci a za ní její argumenty: pcall(kupSemena, 5, 4) zavolá kupSemena(5, 4). pcall vrátí několik hodnot: když všechno proběhne dobře, true a to, co vrátila funkce; při chybě false a chybovou hlášku. V obou případech program pokračuje:
local mince = 20
local function kupSemena(cena, balicky)
local naklady = cena * balicky
if naklady > mince then
error("Málo mincí")
end
mince = mince - naklady
return mince
end
print(pcall(kupSemena, 2, 5))
local ok, vysledek = pcall(kupSemena, 5, 4)
if ok then
print("Zbývá mincí: " .. vysledek)
else
print("Chyba: " .. vysledek)
end
print("Hotovo")Vypíše:
true 10
Chyba: main.lua:6: Málo mincí
HotovoObvyklý je druhý způsob: hodnoty uložit do ok a vysledek a podle ok rozhodnout, co vysledek je. Typická chyba je napsat pcall(kupSemena(5, 4)). Se závorkami za kupSemena Lua funkci zavolá hned, ještě před pcall, a její chyba se nezachytí. Stejně jako u každé funkce, kterou předáváte jiné funkci, předejte samotnou funkci a její argumenty zvlášť.
Jak psát:
Pokyny
Eminy mince klesnou pod nulu. Ve funkci kupSemena před placením skončete pomocí error("Málo mincí na " .. plodina, 0), když je naklady větší než mince. Druhý nákup by pak zastavil celý program, a tak všechny tři nákupy zavolejte přes pcall a vypište, co vrátí, například print(pcall(kupSemena, "mrkev", 2, 5)). Program vypíše:
true 10
false Málo mincí na dýně
true 6Nula balíčků se koupit nedá. Na začátek funkce kupSemena přidejte assert s podmínkou balicky > 0 a hláškou "Kupte aspoň jeden balíček". Pak na konci programu vypište pcall(kupSemena, "kukuřice", 3, 0). Nový řádek obsahuje false a hlášku s pozicí, například:
false main.lua:5: Kupte aspoň jeden balíčekNapište funkci zkusKoupit s parametry plodina, cena a balicky. Zavolá kupSemena přes pcall a výsledky uloží do ok a vysledek. Když se nákup povede, vypíše Koupeno: …, zbývá mincí: …, jinak vypíše Nelze koupit …: a chybovou hlášku. Na konci programu zavolejte zkusKoupit("jahody", 4, 1) a zkusKoupit("brambory", 3, 2). Program končí takto:
Koupeno: jahody, zbývá mincí: 2
Nelze koupit brambory: Málo mincí na bramboryZačněte programovat zdarma
10/11