Perl 6

Die Zukunft des Programmierens

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