Lokální a globální proměnné

Od lekce o proměnných píšete local před každou proměnnou a slíbili jsme, že vysvětlíme proč. Teď, když píšete funkce, nastal ten čas.

Každá lokální proměnná má obor platnosti (anglicky scope): část programu, ve které existuje. Začíná na řádku, kde proměnná vznikne, a končí s blokem, ve kterém vznikla: s tělem funkce, podmínky if nebo cyklu, případně s celým programem. Parametry jsou lokální proměnné své funkce. Proměnná vytvořená uvnitř funkce tedy mimo ni neexistuje:

local function spocitejVejce()
    local vejce = 12
    print("Ve stodole: " .. vejce)
end

spocitejVejce()
print(vejce)

Vypíše:

Ve stodole: 12
nil

Mimo funkci žádné vejce není, takže poslední řádek vypíše nil. Každé volání funkce vytvoří její lokální proměnné znovu a po skončení funkce zaniknou. To je užitečné: dvě funkce můžou mít každá svou proměnnou celkem a nikdy si nepřekážejí.

Opačně to ale jde: funkce vidí lokální proměnné vytvořené nad ní, mimo funkci, a dokonce je může měnit:

local mince = 10

local function kupSemena(cena)
    mince = mince - cena
end

kupSemena(3)
kupSemena(2)
print(mince)

Vypíše:

5

A co proměnná bez local? mince = 50 vytvoří globální proměnnou. Globální proměnná nepatří žádnému bloku: od chvíle, kdy vznikne, existuje všude, v každé funkci, až do konce programu. Globální proměnné jsou i print, math a table, které patří k Lua, a proto je můžete používat kdekoli. Když Lua nenajde lokální proměnnou daného názvu, hledá globální, a když neexistuje ani ta, je hodnota nil. Proto volání funkce před její definicí skončilo chybou attempt to call a nil value (global 'ranniPrace').

Globální proměnné vypadají šikovně, ale způsobují chyby, které se špatně hledají:

  • Překlep vytvoří novou proměnnou. Protože proměnná může vzniknout i bez local, Lua nepozná překlep od nové proměnné. mnice = mince + 5 není chyba: Lua potichu vytvoří globální proměnnou mnice a mince se nezmění.
  • Změnit je může cokoli. Globální proměnnou může změnit kterákoli funkce kdekoli v programu, a když má špatnou hodnotu, musíte prohledat celý program. Přepsat jde i print: po print = 5 skončí každé print(…) chybou attempt to call a number value (global 'print').

Nejhorší je zapomenuté local uvnitř funkce:

local function prodejVejce(vejce)
    mince = vejce * 2
    return mince
end

mince = 50
local vydelek = prodejVejce(10)
print("Výdělek: " .. vydelek)
print("Mince: " .. mince)

Vypíše:

Výdělek: 20
Mince: 20

Ema měla 50 mincí a po prodeji vajec má 20? Funkce chtěla vlastní proměnnou, jenže bez local je mince uvnitř funkce stejná globální proměnná jako venku, a funkce ji přepsala. S local mince = vejce * 2 ve funkci by to byly dvě různé proměnné a Ema by o své mince nepřišla.

Proto tento kurz píše local před každou proměnnou i funkci (function prodejVejce bez local vytvoří globální funkci). Každá proměnná pak existuje jen tam, kde je potřeba, a žádná funkce nezmění omylem proměnné jiné funkce. Hodnoty se do funkce dostávají přes parametry a ven pomocí return. Navíc Lua najde lokální proměnné rychleji než globální. Jen nezapomeňte, že obor platnosti začíná na řádku s local: funkce může používat jen lokální proměnné a lokální funkce vytvořené nad ní.

Pokyny

Eminy slepice snášely každý den, ale program vypíše Vajec za týden: 0. Ve funkci spocitejVejce je překlep v názvu proměnné. Lua ho neohlásila, jen potichu vytvořila globální proměnnou. Najděte překlep a opravte ho. Program pak vypíše Vajec za týden: 49.

Teď program vypíše Výdělek: 98 mincí a Mince: 196. Ema ale měla 50 mincí, takže by jich měla mít 148. Proměnná mince ve funkci prodejVejce nemá local, a tak funkce přepíše Eminy mince ze začátku programu. Opravte funkci, aby používala vlastní lokální proměnnou. Program pak vypíše:

Vajec za týden: 49
Výdělek: 98 mincí
Mince: 148

Samotná funkce prodejVejce je pořád globální. Udělejte z ní lokální funkci, stejně jako je spocitejVejce. Program vypíše totéž.

Začněte programovat zdarma

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

Nebo se registrujte pomocí:

6/11