Perl/Subroutinen

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

[Bearbeiten] Subroutinen erstellen

Bei komplexeren Perl-Scripts ist es empfehlenswert, bestimmte Programmteile in selbst definierte Unterprogramme oder Funktionen zu verlagern - so genannte Subroutinen. Auf diese Weise können Sie das Script besser strukturieren. Sinnvoll ist das vor allem bei Programmteilen, die im Laufe des Scripts mehrmals ausgeführt werden. Bevor Sie also eine größere Prozedur mehrmals im Script notieren, sollten Sie die entsprechende Prozedur in eine Subroutine stecken und diese Subroutine an der gewünschten Stelle aufrufen.

Beispiel
#!/usr/bin/perl -w
 
use strict;
use CGI::Carp qw(fatalsToBrowser);
 
print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Test</title></head><body>\n";
 
my $Ergebnis = 1 + 2 * 3 + 4 * 5 + 6 * 7 + 8 * 9;
Ausgabe();
$Ergebnis = sqrt(sqrt(81));
Ausgabe();
 
print "</body></html>\n";
 
 
sub Ausgabe {
 print "Das Ergebnis lautet: <b>$Ergebnis</b><br>\n";
}
Im Beispiel wird eine Subroutine mit dem Namen Ausgabe erstellt. Eine Subroutine beginnt mit dem Schlüsselwort sub. Dahinter folgt ein frei wählbarer Name, der den Namenskonventionen von Perl entsprechen muss. Der gesamte Inhalt der Subroutine muss in geschweiften Klammern stehen. Sie können beliebige und beliebig viele Anweisungen innerhalb der Subroutine notieren. Mit ihrem Namen und runden Klammern dahinter rufen Sie eine Subroutine auf. Der Aufruf ist eine eigene Anweisung, muss also wie andere Anweisungen mit einem Semikolon abgeschlossen werden. Im obigen Beispiel kommt zweimal die Anweisung Ausgabe(); vor. Dadurch wird die Subroutine mit dem Namen Ausgabe aufgerufen.
Beachten Sie: Anweisungen in Subroutinen werden nur ausgeführt wenn die Subroutine aufgerufen wird.

Es ist egal, an welcher Stelle im Script eine Subroutine steht. Sie kann im Prinzip überall stehen. Es ist allerdings sinnvoll, alle Subroutinen optisch getrennt vom direkt ausgeführten Hauptprogramm zu notieren.

Beim Aufruf könnten Sie anstelle von Routine(); auch &Routine; oder &Routine(); notieren. Die erste Art ist jedoch am empfehlenswertesten, vor allem bei Aufrufen ohne Klammern kann es zu Fehlern kommen.

Wenn Sie - wie im obigen Beispiel - mit use strict; arbeiten, müssen Sie bekanntlich alle Variablen vor ihrer ersten Verwendung deklarieren. Damit wird aber auch der Geltungsbereich einer Variablen eingeschränkt. Eine Subroutine stellt einen eigenen Block und Geltungsbereich dar. Wenn Sie also beispielsweise innerhalb einer Subroutine mit my $Variable=1; eine Variable deklarieren und im Hauptprogramm versuchen, mit print $Variable den Inhalt auszugeben, führt dies zu einer Fehlermeldung, da $Variable im Hauptprogramm nicht bekannt ist. Umgekehrt ist es anders: Variablen, die im Hauptprogramm deklariert sind, sind auch in Subroutinen verfügbar. Im obigen Beispiel wird ja von dieser Möglichkeit Gebrauch gemacht. Generell ist es auch aus diesem Grund bei größeren Scripts sinnvoll, möglichst viel Code mit Variablendeklarationen in Subroutinen zu packen und im Hauptprogramm so wenig Variablendeklarationen wie möglich zu haben. Denn globale Variablen können tendenziell leichter zu logischen Fehlern im Programmablauf führen, da sie nicht so leicht zu kontrollieren sind wie Variablen in begrenzten Subroutinen.

Das Überschreiben von vordefinierten Perl-Funktionen ist ebenfalls möglich. Wenn Sie zum Beispiel die Funktionsweise einer vordefinierten Funktion ergänzen möchten, definieren Sie einfach eine neue Subroutine mit dem entsprechenden Namen. Einige Perl-Module machen von dieser Möglichkeit Gebrauch. Um auf die ursprüngliche Funktion zuzugreifen, setzen Sie einfach ein CORE:: vor den Namen.

[Bearbeiten] Subroutinen mit Parametern aufrufen

Beim Aufruf können Sie einer Subroutine Daten übergeben, die von der Subroutine verarbeitet werden sollen.

Beispiel
#!/usr/bin/perl -w
 
use strict;
use CGI::Carp qw(fatalsToBrowser);
 
print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Test</title></head><body>\n";
 
formatHTML("Hallo User","h1");
formatHTML("Dein Browser gibt sich aus als $ENV{HTTP_USER_AGENT}","i");
 
print "</body></html>\n";
 
 
sub formatHTML {
 my $Inhalt = shift;
 my $Format = shift;
 print "<$Format>$Inhalt</$Format>";
}
Das Beispiel definiert eine Subroutine namens formatHTML. Im oberen Teil des Scripts können Sie sehen, wie diese Subroutine aufgerufen wird. Mit dem Aufruf formatHTML("Hallo User","h1"); werden der Subroutine zwei Parameter übergeben. Denn die Subroutine soll die Aufgabe haben, aus einem übergebenen Text und einem übergebenen HTML-Elementnamen ein HTML-Konstrukt, bestehend aus Anfangs-Tag, Inhalt und End-Tag auszugeben.

Die Subroutine erwartet also zwei Parameter. Interessant ist, wie sie die Parameter abfragt. Dazu benutzt sie einfach die Perl-Funktion shift und weist deren Rückgabewert einem Skalar zu. Um diese Anweisung zu verstehen, ist es wichtig zu wissen, dass Parameter, die einer Subroutine übergeben werden, in der vordefinierten Variablen @_ stehen. Diese Variable enthält die Liste aller Parameter, die der Subroutine übergeben wurden. Der erste Parameter steht dann in $_[0], der zweite in $_[1] usw. Eleganter ist es jedoch, sich die Parameter mit der shift-Funktion zu holen. Da shift beim Aufruf kein Parameter übergeben wird, wendet die Funktion ihre Arbeit automatisch auf die vordefinierte Variable @_ an. Die Funktion entfernt das erste Element der Liste und gibt es zurück. Durch wiederholtes Aufrufen von shift kann sich eine Subroutine also nach und nach alle Parameter abholen, die ihr übergeben wurden.

Die Subroutine im Beispiel holt sich also den ersten Parameter und speichert ihn in $Inhalt und den zweiten in $Format. Dann erzeugt sie eine print-Ausgabe und baut darin das gewünschte HTML-Konstrukt zusammen. Bei jedem Aufruf aus dem Hauptprogramm bewirkt die Subroutine also eine Ausgabe im Browser mit den übergebenen Parametern.
Beachten Sie: Sie müssen nirgendwo festlegen, wie viele und welche Parameter eine Subroutine übergeben bekommen kann. Eine Subroutine, die nicht weiß, wie viele Parameter sie übergeben bekommt, kann die übergebene Parameterliste beispielsweise mit einer foreach-Schleife in der Form foreach(@_) abarbeiten.

[Bearbeiten] Rückgabewerte bei Subroutinen

Subroutinen können Werte zurückgeben. Subroutinen, die Parameter übergeben bekommen, damit etwas tun und die verarbeiteten Daten zurückgeben, entsprechen am ehesten dem, was man unter einer Funktion versteht. Die eingebauten Perl-Funktionen folgen diesem Schema, aber auch die meisten Subroutinen, die Sie in Modulen aufrufen können, arbeiten als Funktionen.

Beispiel
#!/usr/bin/perl -w
 
use strict;
use CGI::Carp qw(fatalsToBrowser);
 
print HTMLKopf();
print HTMLCode("h1","Hallo!","font-size:24pt; color:red");
print HTMLCode("p","Wie geht's?","");
print HTMLFuss();
 
 
sub HTMLKopf {
 my $Kopf = "Content-type: text/html\n\n".
  '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'."\n".
  "<html><head><title>Test</title></head><body>\n";
 return($Kopf);
}
 
sub HTMLFuss {
my $Fuss = "<hr>\n<script type=\"text/javascript\"><!--\n".
            "document.write(\"URL-Adresse: \"+document.URL);\n//--></script>\n".
            "</body></html>\n";
 return($Fuss);
}
 
sub HTMLCode {
 my $Tag = shift;
 my $Inhalt = shift;
 my $Style = shift;
 unless(defined($Style) and length($Style)) {
  return("<$Tag>$Inhalt</$Tag>");
 }
 else {
  return("<$Tag style=\"$Style\">$Inhalt</$Tag>");
 }
}
Das Beispiel weitet die Subroutinen-Technik zum Erzeugen von HTML-Code weiter aus. Es gibt insgesamt drei Subroutinen: HTMLKopf und HTMLFuss setzen mit Hilfe des Operators für Zeichenkettenverknüpfung HTML-Code in einem Skalar zusammen. Am Ende wird dieser Skalar mit der Funktion return zurückgegeben.

Etwas komplexer ist die Subroutine HTMLCode. Sie erwartet drei Parameter, nämlich einen für das zu erzeugende HTML-Element, einen für dessen Inhalt, und einen für eventuelle CSS-Eigenschaften zur Formatierung des Elements. Abhängig davon (mit unless wird die entsprechende Weiche gestellt), ob der dritte Parameter einen Inhalt hat, wird der gewünschte HTML-Code zusammengesetzt und das gesamte Konstrukt mit return zurückgegeben.

Im Hauptprogramm stehen nur ein paar print-Anweisungen. Die Funktion print ist so leistungsfähig, dass sie als übergebene Parameter für das, was sie ausgeben soll, auch Aufrufe anderer Funktionen oder eigener Subroutinen erlaubt. Genau davon wird im Beispiel Gebrauch gemacht. Ausgegeben wird dabei der Return-Wert der jeweils aufgerufenen Subroutine. Ebenso könnten Sie den Return-Wert natürlich einer Variablen zuordnen oder etwas anderes damit tun.
Beachten Sie: Subroutinen können alle Arten von Variablen zurückgeben, also neben Skalaren auch Listen/Arrays, Hashes und Referenzen. Die aufrufende Anweisung muss dafür sorgen, dass der zurückgegebene Wert im richtigen Variablenformat gespeichert wird. Wenn in einer Subroutine namens TeileErmitteln beispielsweise notiert ist:
return(@Ermittelte);
dann könnte eine aufrufende Anweisung etwa lauten:
my @Teile = TeileErmitteln();
Falls Aufrufspeicher und Rückgabewert nicht vom gleichen Typ sind, greift automatisch die Kontext-Bewertung von Perl. Wenn Sie beispielsweise die gleiche Subroutine aufrufen mit:
my $Ergebnis = TeileErmitteln();
Dann ist das, als ob da stünde: $Ergebnis = @Ermittelte. Das Ergebnis besteht in dem Fall darin, dass in $Ergebnis die Anzahl der zurückgegebenen Array-Elemente steht, weil Perl bei einer Liste im skalaren Kontext die Anzahl der Array-Elemente liefert.
Meine Werkzeuge
Namensräume

Varianten
Aktionen
Übersicht
Index
Mitmachen
Werkzeuge
Spenden
SELFHTML