# Variablen und Symboltabellen

- Symboltabellen von Packages
- Globale Variablen und `our()`
- Lexikalische Variablen mittels `my()`
- Dynamische Variablen mittels `local()`
- Unterschiede zwischen `my()` und `local()`

## Symboltabellen von Packages

Wie im Abschnitt Packages beschrieben, gibt es in Perl Namensräume (Packages), die jeweils ihre eigenen Variablen besitzen. Diese Variablen sind in sogenannten Symboltabellen gespeichert. Die Tabelle eines jeden Package ist in Form eines Hash abgelegt; um darauf zuzugreifen stellt man dem Package-Namen ein "`%`" voran und hängt zwei Doppelpunkte "`::`" an.

`#!/usr/local/bin/perl ### Package "main" $main_var1; @main_var2 = (2,3); package hallo; ### Package "hallo" $hallo_var; package main; ### wieder zurück in "main" foreach $v (keys %hallo::) { print "hallo> $v\n" } foreach $v (keys %main::) { print "main> $v\n" }`

Die erzeugte Ausgabe ist recht umfangreich, da auch alle vordefinierten Variablen in der Symboltabelle von `main` enthalten sind. Man beachte, daß in `%main::` (man kann hier stattdessen auch die Kurzform `%::` verwenden) nur der jeweilige Name einer Variablen erscheint; ein Präfix (wie etwa "`$`") wird weggelassen.

Hier ein Ausschnitt der Programmausgabe:

`hallo> hallo_var main> main_var1 main> main_var2 main> v main> hallo:: main> 0`

Die Symboltabelle des Packages `hallo` enthält nur die Variable `$hallo_var`, während sich in `main` neben den explizit verwendeten Variablen `$main_var1`, `@main_var2` und `$v` auch der Name der neuen Symboltabelle `%hallo::` findet. Außerdem stehen dort vordefinierte Variablen wie `$0`, welche den Namen des gerade ausgeführten Skripts beinhaltet.

[Seitenanfang]

## Globale Variablen und `our()`

Wie im obigen Abschnitt schon gezeigt wurde, kann auf Variablen, die "einfach so" deklariert oder verwendet werden, innerhalb des jeweiligen Packages direkt zugegriffen werden. Solche Variablen werden global genannt, da sie an jeder Stelle des Programms zur Verfügung stehen; selbst wenn sie in einem Unterprogramm deklariert werden.

Oft sind globale Variablen zwar praktisch, sie können ein Programm aber auch schnell unübersichtlich machen. Deswegen empfiehlt es sich, globale Variablen nur dort zu verwenden, wo sie notwendig sind. Damit man nicht versehentlich globale Variablen einführt, sollte man immer das Pragma `use strict` verwenden.

Benutzt man `use strict`, so muß man bei jeder Variable angeben, welchen Gültigkeitsbereich sie haben soll. Globale Variablen markiert man ab Perl 5.6.x mit der Deklaration `our()`.

`#!/usr/local/bin/perl -w use strict; use 5.6.0; ### "our" funktioniert ### erst ab Perl 5.6.0 our $var = 123; sub routine { our $vr = "Hallo"; print "$vr\n"; } routine(); print "$var\n"; print "$main::vr\n";`

`Hallo 123 Hallo`

Auf eine mit `our` deklarierte Variable kann man innerhalb des umschließenden Blocks, der Datei oder dem Argument der Funktion `eval()` zugreifen, ohne einen Packagenamen angeben zu müssen. Im obigen Beispiel ist der Gültigkeitsbereich von `$var` die gesamte Datei, während der "einfache" Zugriff auf `$vr` nur innerhalb des Unterprogramms `routine` (in diesem Falle der umschließende Block) möglich ist. Allerdings kann man mit Hilfe des Packagenamens auch außerhalb der Subroutine auf `$vr` zugreifen.

Eine `our`-Variable ist u.U. sogar über Package-Grenzen hinweg sichtbar, es kann jedoch jedes Package jeweils eigene Variablen mittels `our` deklarieren.

`#!/usr/local/bin/perl -w use strict; use 5.6.0; ### "our" funktioniert ### erst ab Perl 5.6.0 our($v1,$v2); $v1 = 1; $v2 = 2; package name; print "$v1 $v2\n"; our $v2 = 9; print "$v1 $v2 $main::v2\n";`

`1 2 1 9 2`

Die Variable `$v1` ist in der ganzen Datei einfach über ihren Namen verfügbar, während es von `$v2` zwei Exemplare gibt. Nach der Deklaration im Package `name` kann auf die in `main` deklarierte Variable über den Package-Namen zugegriffen werden. Ohne Angabe des Packages wird die zuletzt deklarierte `our`-Variable verwendet (unabhängig vom aktuell gültigen Package).

Für ältere Perl-Versionen (< 5.6.0) deklariert man globale Variablen außerhalb von Blöcken mit Hilfe von `my()` (siehe folgenden Abschnitt).

[Seitenanfang]

## Lexikalische Variablen mittels `my()`

Jede Variable, die mit `our` deklariert oder auch "einfach so" ohne eine Deklaration verwendet wird, wird in die Symboltabelle des jeweils aktuellen Packages aufgenommen.

Deklariert man dagegen eine Variable mit dem Operator `my`, so wird die entsprechende Variable in einer anderen Tabelle abgelegt, auf die kein expliziter Zugriff möglich ist.

`#!/usr/local/bin/perl -w use strict; use 5.6.0; ### "our" funktioniert ### erst ab Perl 5.6.0 our $var_1; my $var_2; $var_1 = 42; $var_2 = "Perl"; foreach $v (keys %::) { ### Symboltabelle von "main" if($v =~ /^var/) { print "$v\n" } }`

Hier erscheint in der Programmausgabe nur "`$var_1`", nicht aber "`$var_2`".

Neben der Tatsache, daß `my`-Variablen in einer eigenen Tabelle verwaltet werden, ist von besonderer Bedeutung, daß sie nur einen recht beschränkten Gültigkeitsbereich besitzen. Eine durch `my` erzeugte Variable steht nur in dem aktuellen Block (definiert durch geschweifte Klammern "`{...}`"), der aktuellen Datei oder innerhalb eines Arguments von `eval()` zur Verfügung. Außerhalb davon existieren diese Variablen nicht, es ist also (im Gegensatz zu `our`-Variablen) auch mit Hilfe des Package-Namens dort kein Zugriff möglich

Es kann in einem Package durchaus zwei Variablen gleichen Namens geben: eine in der Symboltabelle und eine, die durch einen Aufruf von `my` entstanden ist. In einem solchen Falle wird bei einfacher Verwendung des Bezeichners auf die `my`-Variable zugegriffen.

`#!/usr/local/bin/perl -w use strict; use 5.6.0; ### "our" funktioniert ### erst ab Perl 5.6.0 our $ab = "main"; { my $ab; $ab = "Block"; print "$ab\n"; ### "Block" print "$main::ab\n"; ### "main" } print "$ab\n"; ### "main"`

Im Block in der Mitte des Programms existiert neben "`$ab`" der Symboltabelle von `main` (Zugriff über voll qualifizierten Namen "`$main::ab`" möglich) auch eine `my`-Variable gleichen Namens. Letztere verschwindet aber wieder, sobald der umschließende Block verlassen wird.

Es ist übrigens durchaus möglich, `my`-Deklarationen zu "schachteln":

`#!/usr/local/bin/perl -w use strict; my $ab = "main"; { my $ab; $ab = "Block"; print "$ab\n"; ### "Block" } print "$ab\n"; ### "main"`

Man bezeichnet solche Variablen als lexikalisch, weil deren Gültigkeitsbereich schon alleine durch Untersuchung des Programmcodes feststellbar ist.

Benötigt man in einem Perl-Programm eine lokale Variable, so sollte man im allgemeinen `my` verwenden. Lediglich in speziellen Situationen ist es angebracht, stattdessen `local` (siehe nächsten Abschnitt) zu benutzen.

[Seitenanfang]

## Dynamische Variablen mittels `local()`

Auch der Operator `local` schränkt den Gültigkeitsbereich einer Variablen ein. Allerdings unterscheidet sich der Mechanismus grundlegend von dem des Operators `my`.

Wird eine Variable durch `local` deklariert, so wird der aktuelle Wert dieser Variablen (sofern vorhanden) gesichert. Anschließend können dieser Variablen neue Werte zugewisen werden. Wird der Block, in dem die `local`-Deklaration erfolgte, verlassen, so wird der ursprüngliche (gesicherte) Wert wiederhergestellt.

`#!/usr/local/bin/perl -w $ab = 123; print "Main: $ab\n"; { local $ab; $ab = 456; print "Block: $ab\n"; } print "Main: $ab\n";`

`Main: 123 Block: 456 Main: 123`

Bei der Deklaration mit `local` wird keine neue Variable auf irgendeinem Stack erzeugt (wie bei `my`), sondern es wird nur der Inhalt neu zur Verfügung gestellt. Die entsprechende Variable ist also nach wie vor global zugänglich.

Daß die Variable nach wie vor eine globale Variable ist, erkennt man auch im folgenden Beispiel:

`#!/usr/local/bin/perl -w $x = 'x (main)'; print "Main: \$x = $x\n"; { local $x = 'x (local)'; print "Block: \$x = $x\n"; print "Symboltabelle: \$::x = $::x\n"; unterpr(); } print "Main: \$x = $x\n"; sub unterpr { print "unterpr(): \$x = $x\n"; }`

`Main: $x = x (main) Block: $x = x (local) Symboltabelle: $::x = x (local) unterpr(): $x = x (local) Main: $x = x (main)`

Sowohl in der (globalen) Symboltabelle als auch in der Subroutine `unterpr()`, die sich, betrachtet man den Quell-Code des Programms, außerhalb des Blockes mit der `local`-Deklaration befindet, wird für `$x` der Wert "`x (local)`" ausgegeben. Der ursprüngliche Wert wird erst wiederhergestellt, wenn in der Folge des Programmablaufs der Block verlassen wird, in dem die `local`-Deklaration stattfand.

Da die Gültigkeit von `local`-Variablen somit durch den Programmablauf bestimmt wird, spricht man auch von Laufzeit- oder dynamischen Variablen.

[Seitenanfang]

## Unterschiede zwischen `my()` und `local()`

Die folgende Tabelle zeigt noch einmal schematisch den Unterschied zwischen `my` und `local`. Markiert sind diejenigen Werte, die ein "`print $v;`" an der entsprechenden Stelle im Code ausgeben würde.

> Zeile | Code | Symboltabelle von `main` | `local`-Stack | Tabelle für `my`-Variablen
> --- | --- | --- | --- | ---
> 1 | `$v = 42;` | v = 42 |  |
> 2 | `{ local $v = 100;` | v = 100 | v = 42 |
> 3 | `{ my $v = 7;` | v = 100 | v = 42 | v = 7
> 4 | `}` | v = 100 | v = 42 |
> 5 | `}` | v = 42 |  |

In Zeile 1 wird eine globale Variable "`$v`" angelegt und mit dem Wert 42 belegt. Wird eine `local`-Variable erzeugt (Zeile 2), so überdeckt der neue Wert den alten; letzterer wird auf einem internen "Stapel" (stack) gesichert. Unabhängig davon können mit Hilfe von "`my`" lexikalische Variablen erzeugt werden (Zeile 3), die in einer eigenen internen Tabelle verwaltet werden. Die Gültigkeit der `my`-Variable endet mit der schließenden Klammer in Zeile 4. Mit dem Blockende in Zeile 5 wird der Gültigkeitsbereich der `local`-Variable verlassen und der ursprüngliche Wert wird vom Stack wiederhergestellt.

Auf die Variable in der Symboltabelle kann in diesem Beispiel immer mittels "`$main::v`" zugegriffen werden. Existiert zusätzlich eine `my`-Variable, so bezieht sich "`$v`" (ohne "`main::`") immer auf diese (nicht auf das globale "`$v`"). Ein Zugriff auf den `local`-Stack ist hingegen nicht möglich.

Eine Situation, in der lokale Variablen nicht mittels `my` erzeugt werden können, sind die speziellen in Perl vordefinierten Variablen, wie etwa `$"` (Zeichen, das die Elemente eines Arrays voneinander trennt, wenn es innerhalb von doppelten Anführungszeichen interpoliert wird). Man kann wie folgt in einem Programmblock eine Neudefinition einer globalen Variable vornehmen, ohne den ursprünglichen Wert explizit sichern und am Ende wieder zurücksetzen zu müssen:

`#!/usr/local/bin/perl -w $" = ','; @a = (10,20,30); print "@a\n"; { local $" = ' - '; print "@a\n"; } print "@a\n";`

`10,20,30 10 - 20 - 30 10,20,30`

[Seitenanfang]

Autor: Eike Grote | Version: 2.05 (24.1.2012)