Variablen und Symboltabellen

[ <= ] [ HOME ] [ INHALT ] [ INDEX ] [ => ]

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.


[ <- ] [ HOME ] [ INHALT ] [ INDEX ] [ -> ]

Lexikalische Variablen mittels my()

Jede Variable, die "einfach so" (wie diejenigen im Beispiel des vorherigen Abschnittes) 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

$var_1 = 42;
my $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. Während nicht besonders deklarierte Variablen (wie $var_1 im obigen Beispiel) im gesamten Package benutzt werden können (und über den voll qualifizierten Namen wie etwa $main::var_1 auch in anderen Packages), so ist eine durch my erzeugte Variable nur in dem aktuellen Block (definiert durch geschweifte Klammern "{...}"), der aktuellen Datei oder innerhalb eine Arguments von eval() zugänglich.

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

$a = "main";
{
    my $a;
    $a = "Block";

    print "$a\n";             ### "Block"
    print "$main::a\n";       ### "main"
}
print "$a\n";                 ### "main"

Im Block in der Mitte des Programms existiert neben "$a" der Symboltabelle von main (Zugriff über voll qualifizierten Namen "$main::a" 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

my $a = "main";
{
    my $a;
    $a = "Block";
    print "$a\n";   ### "Block"
}
print "$a\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.


[ <- ] [ HOME ] [ INHALT ] [ INDEX ] [ -> ]

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

$a = 123;
print "Main:  $a\n";

{
   local $a;
   $a = 456;
   print "Block: $a\n";
}

print "Main:  $a\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.


[ <- ] [ HOME ] [ INHALT ] [ INDEX ] [ -> ]

Unterschiede zwischen my() und local()

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

Code Symboltabelle
von main
Tabelle für
my-Variablen
local-Stack Kommentar
$v = 42; v = 42     Globales $v
{
  local $v = 100;
v = 100   v = 42 Inhalt von $v wird ersetzt
  {
   my $v = 7;
v = 100 v = 7 v = 42 Lexikalische Variable $v
  } v = 100   v = 42 Ende des my-Blocks
} v = 42     Ende des local-Blocks

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 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 so 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


[ <= ] [ <- ] [ HOME ] [ INHALT ] [ INDEX ] [ -> ] [ => ]

Autor: Eike Grote Letzte Änderung: 01.11.1999