ReferenzenPerl

Bis jetzt haben wir einige Variablen kennengelernt: skalare Variablen, Arrays und Hashes. Man kann nun auch mit sogenannten Referenzen auf Variablen arbeiten!

SeitenanfangSeitenendeWas ist eine Referenz

Unter einer Referenz kann man sich einen Art Verweis auf ein "Element" aus Perl vorstellen. Es gibt Referenzen auf skalare Variablen, Arrays, Hashes, Funktionen, ... Erzeugt man eine Referenz auf ein Element, so hat man eine zweite Variable (die Referenz), die auf den Inhalt der ursprünglichen Variablen zeigt.

SeitenanfangSeitenendeErzeugung einer Referenz

Die einfachste Art eine Referenz zu erzeugen, arbeitet über den Operator \ - den sog. Referenzoperator:

$begr="hi Leute";
$refBegr=\$begr; # Referenz auf skalare Variable


@zahlen=(1 .. 10);
$z=\@zahlen; # Referenz auf Array


$rZ2=\$zahlen[2]; # Referenz auf das dritte Element von @zahlen


%farben=(
  rot   => '#FF0000',
  gruen => '#00FF00',
  blau  => '#0000FF'
);
$colors=\%farben; # Referenz auf Hash


$red=\$farben{'rot'}; # Referenz auf Hashelement 'rot'


sub hallo{
  print("hallo\n");
}
$subRef=\&hallo; # Referenz auf Funktion
Bemerkung: Der Inhalt einer Referenz zeigt auf den Inhalt der referenzierten Variablen. Bei einer Referenz auf eine Funktion ist es nicht möglich, Parameter anzugeben.

SeitenanfangSeitenendeDereferenzierung

Bleiben wir bei den Beispielen von oben. $refBegr zeigt jetzt auf $begr. Auf den Inhalt der Variablen greift man ganz einfach zu: Man schreibt vor die Referenzvariable und dem $-Zeichen ein weiteres $-Zeichen bei skalaren Variablen. Bei Arrays ist es eben ein @-Zeichen, bei einem Hash ein %-Zeichen und bei einer Funktion ein &-Zeichen.

print "Inhalt der Referenz: ".$$refBegr."\n\n";

print "Die Zahlen sind: @$z\n\n";

print "Farben:";
foreach (key %$colors){
  print "  $_ = $$colors{key}\n";
}
print "\n";

print "rot=".$$red."\n\n";

&$subRef;

Ergibt:

Inhalt der Referenz ist: hi Leute

Die Zahlen sind: 1 2 3 4 5 6 7 8 9 10

Farben:
  blau = #0000FF
  rot = #FF0000
  gruen = #00FF00

rot=#FF0000

hallo

Gar nicht so schwer oder ... ? Die Sache mit dem Zugriff auf den Inhalt über die Referenz nennt man auch Dereferenzierung. Man muss zuerst dereferenzieren (also $, %, etc. vor die Referenz schreiben), um auf den Inhalt zugreifen zu können.

Man kann den Inhalt einer Variable auch über Referenzen manipulieren - also verändern:

$$refBegr.="\u$$refBegr! Wie geht's?";
print $$refBegr."\n\n";

push (@$z, 11..20);
print "@zahlen\n\n";
Hi Leute! Wie geht's?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

SeitenanfangSeitenendeDereferenzierung (kanonische Syntax und Pfeilsyntax)

Neben obiger Dereferenzierung (Syntax bei skalaren Variablen) gibt es auch noch zwei weitere Möglichkeiten zur Dereferenzierung: Zum einen ist da die kanonische Syntax der Form Zeichen{Referenz} - zum Beispiel ${$refBegr} und zum anderen die Pfeilsyntax, die nur bei Hash- und Arrayvariablen möglich ist. Letztere hat die Form: $Referenz->{key} bzw. $Referenz->[Index] - zum Beispiel $colors->{rot} oder $z->[2].

Die kanonische Syntax unterscheidet sich von der ersten Syntax nur von der Einklammerung der Referenz! Das heißt im Grunde kann man mit dieser Schreibweise genauso arbeiten wie oben. Zusätzlich ist jedoch erlaubt zwischen den beiden Klammern Perlcode zu erzeugen. Es muss nur die erwartete Referenz zurückgeliefert werden. Ein Beispiel zur Verdeutlichung:

@zahlen1=(1 .. 10);
@zahlen2=(11 .. 20);

$z1=\@zahlen1;
$z2=\@zahlen2;

$x=12;

print "@{
  if ($x>10) {
    $z2;
  }
  else {
    $z1;
  }
}\n";
11 12 13 14 15 16 17 18 19 20

SeitenanfangSeitenendeFunktionsaufruf mit Referenzen

Naja wir wissen was Referenzen sind - aber wozu kann man diese brauchen? Ein Einsatzgebiet sind Funktionsaufrufe. Will man innerhalb eines Funktionsaufrus Daten ändern, und die geänderten Daten sollen sich auf das Hauptprogramm auswirken, so ist es sinnvoll mit Referenzen zu arbeiten (call-by-reference). Der Umweg über Paramterübergabe und Rückgabe ist umständlich und langsamer. Hier einige Beispiele um dies zu verdeutlichen:

$z=5;
$z=add2_a($z);
print $z."\n";

$z=5;
add2_b(\$z);
print $z."\n";

$z=5;
add2_c($z);
print $z."\n";


sub add2_a{ # umstaendlich
  my $z=$_[0];
  $z+=2;
}

sub add2_b{ # mit Referenz
  my $refZ=$_[0];
  $$refZ+=2;
}

sub add2_c{ # Sonderfall mit @_
  $_[0]+=2;
}
7
7
7

SeitenanfangSeitenenderef-Operator

Einer Referenz wird nicht nur die Adresse zugewiesen - Perlreferenzen enthalten auch den Typ des Inhalts, auf den sie zeigen. Der Operator ref() gibt den Typ der Referenz zurück:

# die Variablen von ganz oben:

print "Referenz refBegr ist ".ref($refBegr)."\n";
print "Referenz z ist ".ref($z)."\n";
print "Referenz colors ist ".ref($colors)."\n";
print "Referenz subRef ist ".ref($subRef)."\n";
Referenz refBegr ist SCALAR
Referenz z ist ARRAY
Referenz colors ist HASH
Referenz subRef ist CODE

SeitenanfangSeitenendeSymbolische Referenzen

Bis jetzt kennen wir nur Referenzen, die auf existierende Variablen zeigen. Wird eine Referenz auf eine nichtexistierende Variable erzeugt, so wird Letztere erzeugt. Dies nennt man eine symbolische Referenz:

$string="begr";
${$string}="Hi Leute!"; # $begr wird erzeugt

print $begr;
Hi Leute!
Bemerkung: Das hier ist in Wirklichkeit keine echte Referenz.

SeitenanfangSeitenendeAnonyme Funktionen

Bis jetzt kennen wir Referenzen auf explizit existierende Funktionen (\&Funtkion). Dann kann man diese Funktion auch ganz normal aufrufen. Will man das aber nur mit Referenz machen, so kann man einer Referenz den gesamten Code der Funktion zuweisen - dies nannt man dann eine anonyme Funktion:

$refHi= sub{
  "hallo ".$_[0]."\nwie geht's?";
};

print &$refHi("billy")."\n";
hallo billy
wie geht's?
 

SeitenanfangSeitenendeAnonyme Arrays

Anonyme Arrays sind Arrays ohne Variablennamen - man kann nur mit Hilfe einer Referenz auf dieses Array zugereifen. Erzeugt wird ein solches Array analog zu einem ganz normalen Array - der einzige Unterschied ist das Verwenden von eckigen Klammern statt der runden:

$refArray=[1, 2, 3, 4, 5];
print $$refArray[1];
2

Es existiert also keine Variable @irgendwas, sondern nur eine Referenz auf die Daten!

Und Folgendes funktioniert auch:

push(@$array, 17, 11);
print $array."\n".join("-", @$array);
ARRAY(0x1a6f0f0)
17-11

SeitenanfangSeitenendeAnonyme Hashes

Analog zu den anonymen Arrays verfährt man mit anonymen Hashes - statt der eckigen Klammern benutzt man jedoch geschweifte:

$refHash={'red', 'FF0000', 'green', '00FF00', 'blue' ,'0000FF'};
print $$refHash{green};
00FF00

Auch hier existiert keine Variable, sondern nur eine Referenz auf die Daten!


Seitenanfang FehlermeldungHilfe zur Fehlermeldung © 2001-2003 Email an den AutorPerl, Lehrstuhl Mathe II, Uni Bayreuth