Funktionen
Manche Aufgaben innerhalb eines Programms müssen öfter als einmal gemacht werden! Um sich Programmierarbeit zu sparen, Übersicht zu gewinnen oder manche Probleme einfacher zu lösen, kann man solche Aufgaben einer Funktion überlassen. Einige Funktionen haben wir schon kennengelernt. Diese wurden jedoch als Operatoren bezeichnet. Der Unterschied zwischen Operator und Funktion ist für uns: Eine Funktion wird aufgerufen mit einem Klammernpaar nach dem Namen der Funktion - ein Operator nicht. Zum Beispiel print("Haus") wird als Funktionsaufruf angesehen, dagegen print "Haus" als Operator.
Definition
Eine Funktion wird mit dem Schlüsselwort sub eingeleitet, gefolgt vom Namen der Funktion und dem dazugehörigen Anweisungsblock. Die Namensgebung entspricht den üblichen Regeln ...
sub subname{
befehl1;
befehl2;
...
}
Eine Funktion heißt definiert, falls der Anweisungsblock angegeben ist. Eine Definition einer Funktion kann überall im Programmtext stehen; vorzugsweise aber am Ende - so mache ich es wegen der Übersicht! Existieren gleichnamige Funktionen innerhalb eines Programms, so wird nur die Letzte benutzt - evtl. weigert sich Perl das Programm auszuführen.
sub begruessung{
print("moin, moin");
}
Funktionsaufruf
Eine Funktion sollte auch benutzt werden können. Dies geschieht durch das Voranstellen von & vor dem Funktionsnamen im Programmtext. Gefolgt vom Namen werden in den Klammern Parameter (kommt gleich) übergeben:
sub frage;
&hi();
print "\n\n";
&begruessung;
print " Leute ";
nachfrage();
print "\n";
frage;
print "\n";
sub begruessung{
print("moin, moin");
}
sub hi{
print("hi Leute");
}
sub nachfrage{
print("wie geht's");
}
sub frage {
print "Freut ihr euch schon auf die naechste Perlstunde?";
}
hi Leute
moin, moin Leute wie geht's
Freut ihr euch schon auf die naechste Perlstunde?
- Existieren keine Parameter, so können die Klammern weggelassen werden.
- Sind Klammern angegeben, so kann auf das & verzichtet werden.
- Existiert ein Prototyp (sub Funktionsname; ohne Anweisungsblock) vor dem ersten Aufruf der Funktion, so kann auf & und das Klammernpaar verzichtet werden.
- Oft ist es sinnvoll ( - ich musste mich auch eines besseren belehren lassen - ), nicht auf das & zu verzichten. Ein Fall: Ich habe in einem Unterprogramm ein Unterprogramm aufgerufen, wobei Letzteres oberhalb definiert war. Erst als ich den Aufruf mit einem & gekennzeichnet habe, fand Perl dieses Unterprogramm auch.
Rückgabewerte
Den Wert, den eine Funktion liefert, wird als Rückgabewert bezeichnet. Zurückgegeben wird der Wert des zuletzt berechneten Ausdrucks!
$a=5;
$b=10;
print "$a + $b = ".&add_a_b;
sub add_a_b{
$a+$b;
}
Es kann auch ein ganzes Array zurückgegeben werden:
sub mySort_a_b{
if ($a<$b) {
($a,$b);
}
else {
($b,$a);
}
}
Parameterübergabe
Die oben genannten Beispiele dienten nur zur Einführung von Funktionen - sie sind eigentlich recht übel programmiert. Besser ist es, wenn man einer Funktion Parameter übergibt anstatt global zu arbeiten:
$a=5;
$b=13;
print "$a + $b = ".add($a,$b);
sub add{
$_[0]+$_[1];
}
- Die Parameter werden in den Klammern nach dem Funktionsnamen durch Kommatas getrennt übergeben (es wird also ein Array übergeben).
- In der Funktion werden auf übergebenen Parameter mit $_[i-ter Parameter] zugegriffen (diese sind also über das Perlspezialarray @_ erreichbar). Dies geschieht per Referenz; d .h. man greift direkt auf die Variable zu, die übergebenen wurde. Es werden also keine Kopien bei der Übergabe angefertigt; $_[i-ter Parameter] verweist also auf den i-ten übergebenen Parameter. Das kann unter Umständen gefährlich sein:
$a=5;
$b=10;
print add_gefaehrlich($a,$b).
i
" ist die Summe von $a und $b\n";
sub add_gefaehrlich{
$_[0]+=$_[1];
}
15 ist die Summe von 15 und 10
Man muss als vorsichtig mit den übergebenen Parametern umgehen! Verändert man diese im Unterprogramm, so sind sie auch im Hauptprogramm geändert.
lokale Variablen, my und local
Ein weiteres Beispiel: Diesmal perfekt addieren und zwar beliebig viele Zahlen:
sub add{
my $sum=0;
foreach $n (@_) {
$sum+=$n;
}
$sum;
}
- Keine Angst!
- my ist ein Operator, der angibt, dass die nachfolgende Variable lokal ist; d. h., Letztere bleibt nur im Bereich des Anweisungsblocks und den Anweisungsblock innerhalb dieses Anweisungsblocks gültig (also hier nur innerhalb der Funktion).
- Mit Hilfe der foreach-Schleife wird das Übergabearray durchlaufen.
- Am Ende muss die Variable $sum noch einmal angegeben werden, denn Perl gibt den letzten 'berechneten' Wert zurück und das ist ohne dem $sum; in der letzten Zeile der Funktion der implizite Test in der foreach-Schleife 'ist noch ein Wert in der Schleife oder so ähnlich'.
Noch kürzer:
sub add{
my $sum=0;
foreach (@_) {
$sum+=$_;
}
$sum;
}
- Die Spezialvariable $_ wird implizit bei der foreach-Schleife eingesetzt. Perl erwartet eine Variable, findet keine und setzt deshalb $_ ein. Achtung, das ist nur in bestimmten Fällen möglich.
- $_ hat mit @_ nichts zu tun - genau soviel wie @haus und $haus. Es sind eben zwei Paar Stiefel oder eben Variablen.
Es gibt noch eine weitere Art von lokalen Variablen (diese werden mit local eingeleitet) , die meiner Meinung nach nicht so häufig gebraucht werden. (Mir fällt eben kein besonders gutes Beispiel ein, wo diese gebraucht werden könnten!). Für local-Variablen gilt: Sie sind in dem ganzen Unterprogramm, in dem sie mit local deklariert gültig, und zusätzlich in allen Unterprogrammen, die vom Ersteren aufgerufen werden.
$my_x=10;
$local_x=20;
sub1();
print "local_x $local_x\n".
"my_x $my_x\n\n";
sub sub1{
local $local_x=200;
my $my_x=100;
print "local_x $local_x\n".
"my_x $my_x\n\n";
sub2();
}
sub sub2{
print "local_x $local_x\n".
"my_x $my_x\n\n";
}
local_x 200
my_x 100
local_x 200
my_x 10
local_x 20
my_x 10
Erklärung:
- Als erstes wurden die zwei Variablen $my_x und $local_x global definiert.
- Es wird anschließend das Unterprogramm sub1 aufgerufen. Dort werden die beiden Variablen lokal neu definiert (die beiden alten Variablen bleiben erhalten).
- Die erste Variable als my-Variable - diese bleibt nur im aktuellen Anweisungsblock und den Anweisungsblocks innerhalb dieses Anweisungsblocks gültig, aber nicht in den Unterprogrammen, die im Anweisungsblock aufgerufen werden, definiert - und
- die zweite Variable als local-Variable; sie bleibt im ganzen Unterprogramm und den Unterprogrammen, die vom ersten Unterprogramm aufgerufen werden, gültig.
- Außerhalb von den oben genannten Bereichen sind wieder die globalen Variablen gültig.