16. Kde premenná platí: lokálne, globálne, MODULE
Na čo to je
Doteraz si premenné deklaroval vnútri procedúry. Taká premenná patrí len tej procedúre. Keď má hodnotu vidieť viac rutín – skóre, počet životov – deklaruje sa mimo rutín.
Ako sa to píše
BYTE score ; globálna: pred prvou rutinou
PROC Something()
BYTE helper ; lokálna: na začiatku rutiny
…
RETURN
MODULE ; dovolí ďalšie globálne deklarácie za rutinou
BYTE lives
PROC Main()
…
RETURN| Druh | Kde sa deklaruje | Kto ju vidí |
|---|---|---|
| globálna | na začiatku súboru pred prvou rutinou, alebo za slovom MODULE | všetky rutiny, ktoré sú v súbore pod ňou |
| lokálna | na začiatku rutiny (aj parametre sú lokálne) | len tá rutina |
MODULE je potrebné, keď chceš deklarovať globálne premenné až za nejakou rutinou. Bez neho by prekladač ohlásil, že deklarácie musia byť pred príkazmi.
Celý program
Súbor examples/scope.act:
; Where a variable lives
BYTE score=[0] ; global: every routine below sees it
PROC AddPoints(BYTE points)
BYTE bonus ; local: only AddPoints sees it
bonus=points/10
score==+points+bonus
RETURN
PROC Counter()
BYTE calls=[0] ; a local keeps its value between calls
calls==+1
Print("Counter was called ")
PrintB(calls)
PrintE(" times")
RETURN
PROC Hide()
BYTE score ; a local with the name of a global hides it
score=200
Print("Inside Hide: ")
PrintBE(score)
RETURN
MODULE ; global declarations after a routine need MODULE
BYTE lives=[3]
PROC Main()
AddPoints(20)
AddPoints(50)
Print("Score: ")
PrintBE(score)
Counter()
Counter()
Counter()
Hide()
Print("Score after Hide: ")
PrintBE(score)
Print("Lives: ")
PrintBE(lives)
RETURNPreklad a spustenie
action26 scope.act --simČo uvidíš
Score: 77
Counter was called 1 times
Counter was called 2 times
Counter was called 3 times
Inside Hide: 200
Score after Hide: 77
Lives: 3Ako to funguje
scoreje globálna.AddPointsju mení,Mainju vypisuje – obe pracujú s tou istou premennou. Po dvoch volaniach je v nej 20 + 2 + 50 + 5 = 77.bonusje lokálna. MimoAddPointsneexistuje; keby si ju použil vMain, prekladač ohlási neznáme meno.callsvCountersi pamätá hodnotu medzi volaniami. To je zvláštnosť Action!, o ktorej je ďalšia časť.scorevHideje iná premenná. Lokálna premenná s rovnakým menom globálnu zakryje: vnútriHideznamenáscoretú lokálnu. Globálna ostane nedotknutá – po návrate je v nej stále 77.livesje deklarovaná zaMODULEa vidí ju lenMain, lebo len tá je pod ňou.
Lokálne premenné nezanikajú
V mnohých jazykoch lokálna premenná vznikne pri volaní rutiny a po návrate zmizne. V Action! má každá lokálna premenná svoje pevné miesto v pamäti po celý čas behu programu. Z toho plynú tri veci:
- Hodnota prežije medzi volaniami.
Counterto využíva:callssa pri každom volaní zväčší a pamätá si to. - Počiatočná hodnota
=[0]sa nastaví len raz – pri nahraní programu, nie pri každom volaní. Ak má premenná začínať pri každom volaní od nuly, priraď jej nulu príkazom (calls=0). - Rutina nesmie volať samu seba. Volanie rutiny zo seba samej (rekurzia) v Action! prepíše jej vlastné parametre a lokálne premenné, lebo existujú len raz. Program sa preloží, ale počíta zle. Namiesto rekurzie použi slučku.
Globálna alebo lokálna?
- Lokálna, kedykoľvek sa dá. Počítadlo slučky, medzivýsledok – nikto iný ich nepotrebuje a nik iný ich omylom neprepíše.
- Globálna pre stav celého programu: skóre, životy, poloha hráča.
Časté chyby
| Čo sa stalo | Čo povie prekladač |
|---|---|
| lokálna premenná použitá v inej rutine | error ACT008: undeclared name |
globálna deklarácia za rutinou bez MODULE | error ACT006: declaration error: declarations must come before the statements |
| dve premenné s rovnakým menom v tej istej rutine | error ACT006: 'x' is already declared |
| lokálna premenná, ktorú nikde nepoužiješ | warning ACT212: local variable 'x' is never used |
Zakrytie globálnej premennej lokálnou prekladač nehlási – je to dovolené. Keď sa ti „nemení“ globálna premenná, pozri, či si v rutine omylom nedeklaroval lokálnu s rovnakým menom.
Vyskúšaj si
- Použi
bonusvMaina prečítaj si hlásenie prekladača. - Zmaž riadok
MODULEa prelož. Čo sa stane? - Presuň deklaráciu
livesna začiatok súboru kscore. Potrebuješ ešteMODULE?
Zhrnutie
- Globálna premenná je deklarovaná mimo rutín a vidia ju všetky rutiny pod ňou.
- Lokálna premenná a parameter patria jednej rutine.
MODULEdovolí globálne deklarácie medzi rutinami.- Lokálna premenná zakryje globálnu s rovnakým menom.
- Lokálne premenné v Action! nezanikajú: pamätajú si hodnotu a rekurzia nefunguje.
Späť: 15. Funkcie · Ďalej: 17. Mená pre čísla