Listen
Angenommen, Sie wollen ein Programm schreiben, das Namen und Adressen von Personen speichert, eben eine Adressverwaltung.
Dann müßen Sie irgendwie auf die verschiedene Personen zugreifen, das könnte etwa so aussehen:
my $name1; my $name2; my $name3; my $naechster = 1; say "Geben Sie einen Namen zum Speichern ein:"; $name1 = $*IN.get; say "Geben Sie den zweiten Namen zum Speichern ein:"; $name2 = $*IN.get; say "Geben Sie den dritten Namen zum Speichern ein:"; $name3 = $*IN.get; say "Welchen Namen wollen Sie sich anzeigen lassen?" my $auswahl = $*IN.get; if $auswahl == 1 { say $name1; } elsif $auswahl == 2 { say $name2; } else { say $name3; }
Sie sehen schon: das wird hässlich. Und dieses Programm kann erst drei Namen speichern, in dem Arbeitsspeicher Ihres Computers ist aber vermutlich genug Platz, um Millionen von Namen zu speichern.
Wie kann man dieses Dilemma umgehen?
Die Antwort ist: mit Listen. Listen können beliebig viele Elemente enthalten, und man kann einfach auf diese Elemente zugreifen.
Tatsächlich kamen in den bisherigen Programmen schon ab und zu Listen vor, vermutlich ohne, dass Sie das bemerkt hatten:
say "Die Summe von ", $a, " und ", $b, " ist ", $a + $b;
Die verschiedenen Ausdrücke, die von say ausgegeben
werden sollen, werden in einer Liste geschrieben, bei der die
einzelnen Ausdrücke durch Kommata , voneinander getrennt
werden.
Aber wie speichert man eine Liste? Das folgende Beispiel zeigt es:
my @namen; loop (my $i = 0; $i < 3; $i++){ say "Geben Sie Namen Nr.", $i + 1, " ein:"; @namen[$i] = $*IN.get; } say "Welchen Namen wollen Sie sich anzeigen lassen?" my $auswahl = $*IN.get; say @namen[$auswahl - 1];
Dieses Beispiel macht das fast das gleiche wie das vorherige, und ist deutlich kürzer. Und es hat noch einen Vorteil: nur an einer einzigen Stelle steht im Quelltext, dass drei Namen gespeichert werden - man kann die Zahl also leicht erhöhen.
Das Programm im Detail
my @namen;
Hier ist schon die erste Neuerung. Bisher fingen alle Variablen mit
einem Dollar an, diese hier fängt mit einem @ an
(gesprochen "ät").
Das sagt dem Perl-Interpreter, dass die Variable
@namen ein Array ist, also eine Variable, die
Listen speichern kann.
loop (my $i = 0; $i < 3; $i++){ ... }
Wie bei den Schleifen beschrieben, läuft
der Block dieser Schleife drei mal durch, mit den Werten 0, 1 und 2
für $i.
say "Geben Sie Namen Nr.", $i + 1, " ein:";
@namen[$i] = $*IN.get;
Hier wird erst der Benutzer aufgefordert, einen Namen einzugeben.
Dabei ist zu beachten, dass $i von 0 bis 2 läuft, aber
weil Benutzer meistens verwirrt sind, wenn man sie bittet, den Namen
Nummer 0 einzugeben, wir $i + 1 ausgegeben.
Die zweite Zeile ist auch wieder etwas neues:
@name[$i] ist der $i-te Eintrag des Arrays
@name. Dabei wird allerdings bei 0 das Zählen angefangen,
das heißt der erste Eintrag hat den Index 0, der zweite den Index 1
und so weiter.
Dem $i-ten Eintrag wird hier die Eingabe des Benutzer
zugewiesen. Wenn $i den Wert 0 hat, und der Benutzer
"Hans" eingibt, beutet diese Zeile das gleiche wie
@namen[0] = "Hans";
Danach hat das Array @namen einen Eintrag.
Wenn der Benutzer beim zweiten Durchlauf "Horst" eingibt, hat die
Variable $i bereits den Wert 1, und an die zweite Stelle
des Arrays wird "Horst" geschrieben:
@namen[1] = "Horst";
Danach hat das Array die Einträge @namen = "Hans",
"Horst".
Wenn der Benutzer beim dritten Durchlauf "Heinz" eingibt, hat das
Array die Elemente "Hans", "Horst", "Heinz".
say "Welchen Namen wollen Sie sich anzeigen lassen?" my $auswahl = $*IN.get; say @namen[$auswahl - 1];
Hier hat der Benutzer die Möglichkeit, eine Zahl einzugeben, die hoffentlich zwischen 1 und 3 ist.
Diese Zahl wird in $auswahl gespeichert, und dann wird
@namen[$auswahl - 1] ausgegeben. Wenn
$auswahl z.B. 2 ist, wird @namen[1]
ausgegeben, also das zweite Element - "Horst".
Mehr zu Listen
Listen können für sehr viele Aufgaben extrem praktisch sein. Deswegen gibt es viele Möglichkeiten, Listen zu initialisieren, auszulesen und sie zu bearbeiten.
my @a = 1 .. 10; # jetzt hat @a die Form 1, 2, 3, 4, 5, 6, 7, 8, 9 my @b = 0 xx 5; # @b enthält jetzt fünf mal das Element 0 @b.push(1, 2); # dieser Befehl hat die Elemente 1 und 2 an @b angehängt, # d.h. @b ist jetzt 0, 0, 0, 0, 0, 1, 2 @a[2]; # ist 3 @a[2, 3, 5]; # ergibt die Liste 3, 4, 6 @a.elems; # Anzahl der Elemente in @a, also 10 @a.end; # Index des letzten Elements von @a, also 9 # Ein Stern steht für "irgend etwas" oder "alles": @a[3..*] # Alle Elemente ab dem vierten # Ein negativer Index wird von hinten gezählt: @a[*-1] # letztes Element
Listen können beliebige Elemente enthalten, das heißt man kann z.B. Strings und Zahlen gemischt in Listen packen:
my @a = "hallo", 1, 2, "Welt";
Tatsächlich kann man sogar Listen als Elemente von Listen nehmen, dann muss man die Liste allerdings in eckige Klammern schreiben:
my @a = 1, 2, [3, 4, 5], 6; @a.elems; # 4 Elemente: 1, 2, eine Liste, und 6
Da man relativ häufig Arrays initialisieren muss, die aus einzelnen Worten bestehen, gibt es dafür eine eigene Schreibweise:
my @werktage = <Montag Dienstag Mittwoch Donnerstag Freitag>; # das Gleiche wie @werktage = "Montag", "Dienstag", ...
Listen ausgeben
Wenn man eine Liste ohne irgend welche Trennzeichen ausgeben will,
kann man sie einfach an say übergeben. Wenn man die
Elemente trennen möchte, z.B. durch Kommata oder Leerzeichen, kann man
diese Trennzeichen mit join übergeben:
my @werktage = <Montag Dienstag Mittwoch Donnerstag Freitag>; say @werktage; # Ausgabe: MontagDienstagMittwochDonnerstagFreitag say @werktage.join(", "); # Ausgabe: Montag, Dienstag, Mittwoch, Donnerstag, Freitag
Für verschachtelte Listen ist Ergebnis nicht immer unbedingt das,
was man erwartet. Um die Struktur von beliebig verschachtelten Listen
auszugeben, kann man sich mit der Funktion perl eine
String-Repräsentation ausgeben lassen:
my @a = 1, 2, 3, [4, 5, 6], 7; say @a.perl; # Ausgabe: [1, 2, 3, [4, 5, 6], 7]
Das eignet sich zwar nicht für schön formatierte Ausgaben, aber um zu wissen, wie eine Liste (oder etwas beliebiges anderes) aussieht, reicht es.
Listen durchlaufen
Eine Möglichkeit, alle Elemente einer Liste auszugeben, haben Sie oben (in ein wenig anderer Form) schon gesehen:
my @wochentag = <Montag Dienstag Mittwoch Donnerstag Freitag>; loop(my $i = 0; $i < @wochentag.end; $i++){ say @wochentag[$i]; }
Weil das so häufig gebraucht wird, gibt es eine eigene, kompaktere Schreibweise dafür:
my @wochentag = <Montag Dienstag Mittwoch Donnerstag Freitag>; for @wochentag -> my $tag { say $tag; }
Die for-Schleife nimmt eine Liste, hier
@wochentag, und dahinter ist mit einem Pfeil, der aus
Minus-Zeichen und Größer-Zeichen besteht, eine Variable angegeben.
($tag).
Bei jedem Durchlauf der Schleife der wird die Variable
$tag auf ein anderes Element der Liste gesetzt, in der
Reihenfolge, wie sie in der Liste auftauchen.
Von der Kommandozeile lesen
Wenn es Sie in den vorherigen Beispielen genervt hat, dass Sie immer wieder aufs Neue Zahlen auf der Tastatur eingeben müssen, wenn Sie ein Programm haben laufen lassen, dann gibt es gute Neuigkeiten - es geht auch einfacher.
Beim starten eines Programms kann man auf der Kommandozeile noch
weitere Werte mit angeben, die dem Programm in der speziellen Variablen
@*ARGS zur Verfügung stehen.
for @*ARGS -> $a { say "Argument $a" }
Wenn Sie das Programm so starten: ./perl6 kommando.pl 2 3,
dann sieht die Ausgabe so aus:
Argument 2 Argument 3