Perl-Programmierung: Subroutinen
Aus Wikibooks
Inhaltsverzeichnis |
[Bearbeiten] Vorbemerkung
Es wird bei Subroutinen in der allgemeinen Programmierung unterschieden zwischen Prozeduren und Funktionen. Funktionen erzeugen Rückgabewerte, Prozeduren nicht. Diese Unterscheidung ist bei Perl unerheblich, insofern wird an dieser Stelle in der Folge von Funktionen gesprochen.
Funktionen werden immer dann verwendet, wenn sich ein Vorgang mehrfach verwenden lässt. Die Routinenlogik wird dann aus dem Hauptprogramm ausgelagert und mit einem Funktionsaufruf eingebunden. Der Vorteil, dass der Vorgang dann nur einmal programmiert werden muss, liegt auf der Hand. Ein weiterer Vorteil ist, dass auch die Wartung und Modifikation des Programms erleichtert wird, weil Änderungen ebenfalls nur an einer Stelle vorgenommen werden müssen. Ein ausgiebiger Gebrauch von Funktionen ist also empfehlenswert.
[Bearbeiten] Allgemeine Deklaration
[Bearbeiten] Aufbau
sub FUNKTIONSNAME{
DEKLARATIONSBLOCK
ANWEISUNGSBLOCK
return RÜCKGABEVARIABLE;
}
Die Deklaration von Funktionsinternen Variablen erfolgt entweder mit 'local' oder mit 'my', z.B.:
my $param1 = 0; local $param2 = 0;
Bei der Verwendung von 'local' steht die Variable auch untergeordneten Funktionen zur Verfügung.
Die Parameterübergabe erfolgt in Perl nicht wie üblich im Funktionskopf, stattdessen steht das vordefinierte Default-Array '@_' zur Verfügung, zum Beispiel:
my $param1 = $_[0]; local $param2 = $_[1]; ...
[Bearbeiten] Prototyp
Ein Prototyp hat die Aufgabe, dem Hauptprogramm den Namen und die Parametertypen mitzuteilen. Er schreibt sich wie ein reduzierter Funktionskopf:
Beispiel 1, Funktion mit zwei skalaren Übergabeparametern und einem optionalen skalaren Übergabeparameter: sub FUNKTIONSNAME($$;$)
Beispiel 2, Funktion mit einer Übergabeliste: sub FUNKTIONSNAME(@)
[Bearbeiten] Aufruf
Funktionen werden mit Symbol & und FUNKTIONSNAME aufgerufen.
Möglichkeit 1: &FUNKTIONSNAME(PARAMETERLISTE);
Möglichkeit 2: FUNKTIONSNAME(PARAMETERLISTE);
Möglichkeit 3: &FUNKTIONSNAME PARAMETERLISTE;
Bei Verwendung eines Prototyps oder einer Paketfunktion gibt es auch noch die
Möglichkeit 4: FUNKTIONSNAME PARAMETERLISTE;
Anmerkung:
Subroutinen lassen sich ohne und mit Parameterlisten aufrufen. Die Parameter finden sich innerhalb der Funktion in der Struktur @_ wieder und können mit $_[] ($_[0], $_[1] ... usw.) separat angesprochen werden.
Beispiel:
sub groesser{ if ($_[0] > $_[1]){ $_[0]; #ergebnis }else{ $_[1]; #ergebnis = rueckgabewert } }
Aufruf mit &groesser(24,15) liefert als Ergebnis 24. ($_[0]=24 der Rückgabewert).
mit lokalen Variablen:
sub groesser{ local ($a,$b) = ($_[0],$_[1]); if ($a > $b){ $a; }else{ $b; } }
liefert das gleiche Ergebnis wie oben.
Das in C, C++ und anderen Programmiersprachen verwendete return zur Rückgabe des Funktionswertes ist in Perl am Ende einer Funktion optional. Von der Funktion wird immer der Rückgabewert des letzten Befehls zurück gegeben. Die folgende Funktion test liefert zum Beispiel den Wert 1, da dieser bei erfolgreicher Ausführung der festgelegte Rückgabewert von print ist.
sub test{ print "Nichts zu tun.\n\n"; }
[Bearbeiten] Kontext
Eine Besonderheit in Perl ist, dass der Rückgabewert einer Funktion nicht nur von den Parametern abhängt, sondern auch von dem Kontext, in dem der Aufruf erfolgt. Deshalb sind solche Unterprogramme keine Funktionen im strengen Sinne. Das Schlüsselwort 'sub' in Perl ist von "subroutine" = "Unterprogramm" abgeleitet.
Den Kontext muss man auch bei der Verwendung einiger eingebauter Funktionen beachten, zum Beispiel bei der Verwendung der Funktion 'each'.
my %hash = (Kuh => 'Milch', Kamel => 'Wasser', Gnu => 'Freie Software'); while( my $tier,$topic = each(%hash) ){ print $tier," => ",$topic,"\n" } while( my ($tier,$topic) = each(%hash) ){ print $tier," => ",$topic,"\n" }
Liefert die Ausgabe:
=> Gnu => Kamel => Kuh Gnu => Freie Software Kamel => Wasser Kuh => Milch
Bei der zweiten Schleife wird mit den Klammern ein Listenkontext hergestellt. In diesem liefert each ein Schlüssel-Wert Paar. Im skalaren Kontext oben, wird der Variable $topic bei jedem Schleifendurchlauf ein Schlüsselwert zugewiesen.
Um in den eigenen Unterprogrammen, diese Funktionalität nutzen zu können, liefert die Funktion wantarray einen wahren Wert, wenn ein Aufruf in einem Listenkontext erfolgt.
[Bearbeiten] Externe Subroutinen
Viele Funktionen sind bereits in den vielen hundert Modulen im CPAN und anderswo als freie Software verfügbar. Um dabei Namenskonflikte zu vermeiden werden zusammengehörige Funktionen in einem Namensraum zusammengefasst.
Als Beispiel möchte ich das Modul File::Temp nennen. Es verwendet den Namensraum File::Temp und enthält zwei Funktionen, eine zur Erstellung von temporären Dateien (tempfile) und eine für Verzeichnisse (tempdir).
Namensräume sind in Perl hierarchisch aufgebaut und sollten vom Programmierer sinnvoll gewählt werden. Außerdem ist, wie man sieht, der Namensraum meist identisch mit dem Modul. Es kann aber sein, dass umfangreiche Module viele Namensräume nutzen.
Es sollte so sein, dass der gewählte Name in einem Zusammenhang mit der Funktion des Moduls steht. So stehen alle Module im Namensraum File, in einem Zusammenhang mit Dateien.
[Bearbeiten] Laden eines Moduls mit use
use File::Temp;
In dieser Form wird das Modul während der Übersetzungszeit geladen. Außerdem wird eine spezielle Funktion in dem zu ladenden Modul aufgerufen. Ihr Name ist import.
use File::Temp ();
Schreibt man hinter das Modul eine leere Liste, so wird der Aufruf von import übergangen.
use File::Temp qw/ tempfile tempdir /;
In dieser Form zeigt sich woher die spezielle Funktion ihren Namen hat. Es ist häufig so, dass Funktionen in aktuellen Namensraum geladen werden können, sie werden quasi importiert. Genau das soll mit dieser Form von use ausgedrückt werden.
[Bearbeiten] Erstellung
[Bearbeiten] Bibliothek
Eine Bibliothek ist eine Datei, die Funktionsdefinitionen enthält, deren Dateiname auf *.pl endet, und deren letzte Zeile aus dem Code
1;
besteht.
[Bearbeiten] Modul
[Bearbeiten] Einbindung und Aufruf
Eine Bibliothek wird mit 'require' eingebunden:
require("DATEINAME.pl");
Bibliotheksfunktionen werden dann wie interne Funktion aufgerufen.
Ein Modul wird mit 'use' eingebunden
use MODULNAME;
und mit
MODULNAME::FUNKTIONSNAME();
aufgerufen.