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

Action!
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
DruhKde sa deklarujeKto ju vidí
globálnana začiatku súboru pred prvou rutinou, alebo za slovom MODULEvšetky rutiny, ktoré sú v súbore pod ňou
lokálnana 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:

Action!
; 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)
RETURN

Preklad 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: 3

Ako to funguje

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:

  1. Hodnota prežije medzi volaniami. Counter to využíva: calls sa pri každom volaní zväčší a pamätá si to.
  2. 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).
  3. 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?

Časté chyby

Čo sa staloČo povie prekladač
lokálna premenná použitá v inej rutineerror ACT008: undeclared name
globálna deklarácia za rutinou bez MODULEerror ACT006: declaration error: declarations must come before the statements
dve premenné s rovnakým menom v tej istej rutineerror 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

  1. Použi bonus v Main a prečítaj si hlásenie prekladača.
  2. Zmaž riadok MODULE a prelož. Čo sa stane?
  3. Presuň deklaráciu lives na začiatok súboru k score. Potrebuješ ešte MODULE?

Zhrnutie

Späť: 15. Funkcie · Ďalej: 17. Mená pre čísla