Perl6 beschert der Perl5-Syntax einen neuen Anstrich und führt ein richtiges Objektsystem ein. Ein Praxistest anhand der Reimplemtierung eines alten Blackjack-Spiels.
Totgesagte leben länger, heißt es, und das jahrzehntelang herbeigelechzte Perl6 scheint nun tatsächlich Gestalt anzunehmen. Das erfuhr ich kürzlich in Orlando im Bundesstaat Florida, als ich Gelegenheit hatte, eine Woche nach der Massenschießerei dort der Grassroots-Perl-Konferenz YAPC 2016 beizuwohnen.
Etwa zwei Drittel der Vorträge widmete sich Perl5-Themen, aber zu meinem bassen Erstaunen wenden sich nun mehr und mehr Leute in der Community allen Ernstes dem Nachfolger und jahrelangem Sorgenkind Perl6 zu. Schon vor sage und schreibe elf Jahren, auf der OSCON-Konferenz 2005 hatte Damian Conway vollmundig angekündigt, das "Endgame" der Entwicklung sei angebrochen, aber was dann folgte, waren mehrere Rückschläge und Neuanfänge, bis Ende letzten Jahres dann endlich die virtuelle Maschine Rakudo betriebsfähig war, die zwar nicht mit Performance punktet, aber doch zuverlässig Perl6-Code durchrattert.
Was ist Perl6 eigentlich? Um das zu erforschen, ist es hilfreich, zu analysieren, was Perl5 denn gefehlt hat. Manko Nummer eins ist ohne Zweifel ein fest eingebautes Objektsystem. In Perl5 war es nämlich nur notdürftig aufgenietet, und niemand, der einigermaßen bei Verstand war, hätte auch nur in einem mittelgroßen Programm die zu Klassen gestempelten Hashstrukturen oder als Hashelemente eingebaute Attribute verwendet.
Vielmehr haben professionelle Perl-Entwickler seit nunmehr bestimmt zehn Jahren das CPAN-Modul Moose oder einen seiner Ableger genutzt, um Klassen zu definieren und auf deren Attribute so zuzugreifen. Das befreit Entwickler nicht nur von der Fronarbeit, lästigen Boilerplate-Code einzutippen, sondern spannt auch ein Sicherheitsnetz auf, denn der Compiler merkt sofort, falls sich ein Tippfehler eingeschlichen hat. Bei einem falschen Hashkey ist das nicht der Fall und fatale Fehler kommen erst zur Laufzeit und unter Umständen langer Betriebszeit aus ihren Löchern. Eigentlich eine Selbstverständlichkeit für jede moderne Sprache, aber eben in Perl5 historisch bedingt leider nur als Flickwerk implementiert.
Die Macher Larry Wall und Damian Conway spendierten Perl6 also Syntax zur Definition von Klassen und zum Aufrufen von Objektmethoden, denen Entwickler Listen mit benannten Parametern übergeben können. Nebenbei wurden auch noch einige logische Ungereimtheiten in der Perl5-Syntax bereinigt, die sich als Fallstricke für Neuanfänger erwiesen hatten. Und weil man schon mal dabei war, kam noch hier und da geklaute Syntax aus allen möglichen moderneren Sprachen wie Python oder Ruby hinzu, die irgendwie praktischen Nutzen versprach und clevere Tricks beim Programmieren verhieß. Herausgekommen ist eine Sprache mit relativ vielen Sonderzeichen, die die Kompatibilität zum alten Perl5 komplett zerbrach und einen neuen Interpreter namens Rakudo braucht.
Abbildung 1: Foto: Wikipedia, Martin Bahmann (https://commons.wikimedia.org/wiki/File:Schr%C3%B6dinger_cat.png). |
Eines der etwas clever-exotischen neuen Konstrukte in Perl6 sind die sogenannten Superpositionen aus der Feder von Damian Conway. Letzterer hatte die Idee schon vor 13 Jahren auf Konferenzen hausiert und später in einem CPAN-Modul namens Quantum::Superpositions Quanten-Variablen in die Sprache eingeführt. Wie die quantenmechanische Katze in Schrödingers Experiment [4], die gleichzeitig tot und lebendig ist, nehmen diese Variablen mehrere Werte gleichzeitig an. So kann ein Integer gleichzeitig 1 und 2 sein, und addiert man 5 dazu, ist das Ergebnis gleichzeitig 6 und 7. Damals fiel mir dazu als Beispiel das Casino-Spiel Blackjack ein, bei dem ein As entweder 1 oder 11 Augen zählt.
01 use v6; 02 use strict; 03 use Terminal::ANSIColor; 04 05 class Blackjack::Card { 06 has $.rank; 07 has $.suit; 08 has $.val; 09 has $.suit_color; 10 11 method Str() { 12 return colored( 13 "{self.rank}", self.suit_color ); 14 } 15 }
Im Jahre 2003 schrieb ich deshalb eine Kolumne im Linux-Magazin, zusammen mit
einem Perl5-Skript, das ein Blackjack-Spiel mit einem Dealer in Las Vegas
simuliert. Also dachte ich mir diesen Monat, was läge näher, als das alte
Blackjack-Programm von anno dunnemals in modernem Perl6 nachzuimplementieren?
Listing 1 zeigt, wie Perl6 den Klassen-Code für eine Blackjack-Karte
implementiert. Kartenwerte heißen auf Englisch "Rank", also hat die Klasse
Blackjack::Card
in Listing 1 ein Attribut namens "rank"
mit dem
Default-Typ eines Perl-Skalars, der einen String oder Integer beherbergen darf.
Wer in Perl5 schon mit dem Moose-Modul gearbeitet hat, der braucht sich also
mit Perl6 nicht groß umzustellen, die neue Syntax ist fast identisch.
Neben einer Farbe (suit
) verfügt jede Spielkarte noch über einen Zählwert
(val
), und die Darstellungsfarbe auf dem Bildschirm suit_color
. Die
Definitionen in Listing 1 beginnen mit einem Dollarzeichen, das die zugehörigen
Attribute als Perl-Skalare auszeichnet. Alternativ bietet Perl6 für
Attribute auch Arrays (@)
und Hashes (%), sowie beliebige Klassennamen für Objektattribute. Der nach
den "Sigils" genannten Sonderzeichen folgende Punkt zeichnet eine Variable
als Objektattribut aus. Perl6 definiert dazu gleich hinter den Kulissen
praktische Methoden für den lesenden und schreibenden Zugriff (z.B. obj.rank(
"A" )
), sowie benamte Parameterlisten für den Konstruktor, der dann Aufrufe
wie Blackjack::Card.new( rank => "A" )
versteht. Wichtig auch: Perl6
ersetzt den Pfeil ->
durch einen Punkt, aus $o->foo()
in Perl5
wird so $o.foo()
in Perl6. Um innerhalb eines Objekts auf das Objekt selbst
zuzugreifen, dient das Schlüsselwort self
(ohne Sigil).
Strings in Perl6 können nicht nur automatisch interpolierte Variablen
wie in "Hallo $gast"
enthalten, sondern auch dynamisch ausgeführte
Code-Konstrukte in geschweiften Klammern, was besonders
mit der neuen Objektsyntax hilft, falls der Wert nicht in einer
Variablen steckt, sondern aus einer Methode stammt: "Hallo {$o.gast()}"
ersetzt die geschweiften Klammern und alles dazwischen mit
dem Rückgabewert der Methode gast()
auf ein in $o
liegenden Objekt.
Abbildung 2: Der Blackjack-Dealer hat sich eine offene Karte und jedem der vier Spieler am Tisch jeweils zwei Karten zugeteilt (Bild: Wikipedia). |
Wie geht Blackjack nochmal in einem Casino in Las Vegas? An einem halbrunden Kartentisch mit grünem Filzbelag steht ein Kartenausgeber, der Dealer, einer Reihe von Spielern gegenüber und zieht aus einem sogenannten Schuh einzeln Karten von einem 52-blättrigen Pokerblatt.
Um den Kartenzählern unter den Spielern im Casino die Arbeit zu erschweren, enthält ein Kartenschuh gut gemischt bis zu acht Kartenspiele mit 52 Karten. Zuerst gibt der Dealer jedem Spieler am Tisch zwei offene Karten, und anschließend gibt er sich selbst eine offene und eine verdeckte Karte. Dann sind die Spieler an der Reihe, sie können entweder weitere Karten vom Dealer verlangen ("Hit") oder dankend ablehnen ("Stand"). Ziel des Spiels ist es, mit allen gezogenen Karten möglichst nahe an die Gesamtpunktzahl 21 zu kommen, ohne diese zu überschreiten, denn sonst verliert der Spieler automatisch. Sind die Spieler befriedigt, fängt der Dealer an, seine verdeckte Karte offenzulegen und eventuell für sich selbst weitere Karten aus dem Schuh zu ziehen.
In den Casinos von Las Vegas spielt der Dealer wie ein Roboter nach einem festen System: Er zieht neue Karten, bis er mindestens 17 Punkte hat. Kommt zum Beispiel eine Zehn aus dem Schuber, und hinterher eine Sechs, zieht er nochmal, auch wenn's dann meistens rappelt und er mit einer 10-wertigen Karte über das Ziel von 21 hinausschießt und automatisch verliert, auch wenn sein Gegenspieler zum Beispiel bereits bei 13 aufgehört hat zu ziehen. Diese Regel ist bei allen Casinos identisch, mit einer kleinen Variation, der sogenannten "Soft 17" [3]. Diese Regel bestimmt, ob der Dealer auch bei einer 17, die sich aus mindestens einem As zusammensetzt nochmal ziehen muss. Zieht der Dealer zum Beispiel eine As und eine Sechs, hat er 17 und zieht bei einer "Hard 17"-Regel nicht mehr. Schreibt das Casino hingegen "Soft 17" vor, muss er nochmals ziehen, weil seine 17 (wenn das As nicht als 11 sondern als 1 zählt) auch als 1 + 6 = 7 interpretiert werden kann. Das gibt dem Dealer übrigens statistisch einen kleinen Vorteil in die Hand, seine Gewinnchancen wachsen um 0.2%.
Abbildung 3: Das Blackjack-Spiel in Aktion: Hier gewinnt der Casino-Spieler gegen den Dealer. |
In der Kommandozeilenversion des nachfolgend
vorgestellten Skripts blackjack.p6
folgt der Dealer "Soft 17"-Regel und
tritt gegen einen einzigen Spieler, den Aufrufer des Skripts an. Abbildung
3 zeigt einen Durchgang, bei dem der Spieler gegen den Dealer gewinnt.
Zuerst zieht der Dealer eine Dame ("Q" für Queen) und eine verdeckte
Karte, die das Skript naturgemäß nicht anzeigt. Der Spieler erhält zwei
Zweien und tippt "H" ("Hit"), um mehr Karten zu verlangen. Es kommt
ein As ("A") nach, und nachdem ein As im Blackjack entweder eins oder elf
zählt, ist der Wert der Kartenhand nun 5 oder 15, was das Skript mit
"any(5,15)" anzeigt.
Ein erneuter Hit bringt eine Zehn, also zählt die Kartenhand entweder 15 oder 25, wobei letzteres unter den Tisch fällt, weil es 21 übersteigt. Wagemutig drückt der Spieler ein weiters Mal auf "H", erhält wie durch ein Wunder eine Sechs und hat nun genau 21, die alternative 31 fällt unter den Tisch. Der Spieler drückt "s" ("Stand") und dann ist der Dealer an der Reihe, dreht seine verdeckte Karte um (eine Vier), sodass er nun "Q-4" hält, also eine Dame und eine Vier, die zusammen 14 zählen. Das ist weniger als 17, also zieht er gemäß den Casino-Vorschriften eine weitere Karte, bekommt aber einen Buben ("J") und ist nun mit 27 weit über's Ziel hinausgeschossen, verliert also automatisch. Der Spieler erhält den Punkt ("Score: 1") und seine Gesamtpunktzahl ("Total") ist nun ebenfalls 1, da es sein erstes Spiel war. Stunden blendender Unterhaltung für die ganze Familie.
Alle Spielkarten in einem 52-Karten-Blatt repräsentiert ein Objekt der Klasse Blackjack::Deck in Listing 2 Damit der Perl-Parser gleich weiß, dass Perl6-Code vorliegt, und nicht total verwirrt an der neuen Syntax scheitert, gibt "use v6" am Dateianfang die Version in einer Syntax vor, die auch der Perl5-Interpreter versteht und mit einer klaren Fehlermeldung abbricht, sollte jemand ihn versehentlich darauf ansetzen.
01 use v6; 02 use strict; 03 use Blackjack::Card; 04 05 class Blackjack::Deck { 06 has @.ranks = 07 [ flat < A J Q K >, 2..10 ]; 08 has @.suits = 09 < Hearts Spades Diamonds Clubs >; 10 has %.suit_color = 11 flat self.suits Z 12 flat < red black magenta blue >; 13 has @.cards; 14 15 method shuffle() { 16 for self.ranks -> $rank { 17 18 my $val = 10; 19 if $rank ~~ /\d+/ { 20 $val = $rank.Int(); 21 } elsif $rank eq "A" { 22 $val = 1|11; 23 } 24 25 for self.suits -> $suit { 26 self.cards.push( 27 Blackjack::Card.new(:$rank, 28 :$suit, :$val, 29 suit_color => 30 self.suit_color{ $suit } )); 31 } 32 } 33 self.cards = self.cards.pick( * ); 34 } 35 36 method pick() { 37 if self.cards.elems == 0 { 38 self.shuffle; 39 } 40 return self.cards.shift; 41 } 42 }
Zeile 7 definiert mit dem Ausdruck
flat < A J Q K >, 2..10
eine Liste mit allen möglichen Kartenwerten, As-Zehn-Bube-Dame-König,
sowie die Zahlenwerte von 2 bis einschließlich 10. Durch Leerzeichen
getrennte Werte in eckigen Klammern ist die Perl6-Syntax für die
qw(...)
-Listen in Perl5. Den Range-Operator ".."
gab's in Perl5
auch schon, allerdings münden solche Konstrukte nicht wie in Perl5 in
einer langen Liste von Werten, sondern in Listen von Listen, sodass
der Ausdruck den zusätzlichen Operator flat
braucht, um das Ganze
zu einer langen Liste auszuflachen.
Um nun alle Karten im Spiel zu simulieren, geht die Methode shuffle()
ab Zeile 15 in Listing 2 mittels zwei For-Schleifen durch die Attribute
@.ranks
und @.suits
, kombiniert jeweils zwei Einträge zu einer
Karte der Klasse Blackjack::Card, und schiebt das so neu gewonnene Objekt
auf den Array @.cards
. Die Zeilen 18 bis 23 bestimmen den Zählwert
jeder Karte, der Eintrag 1|11
für ein As ist eine der vorher besprochenen
Superpositionen aus den Werten 1 und 11.
Welche Bildschirmfarbe der Hash
%.suit_color
den Kartenfarben zuordnet, bestimmt sich aus der
Verknüpfung von @.suits
und einer ausgeflachten Liste von
Bildschirmfarben in Zeile 12. Der Operator "Z" in Zeile 11 wendet
auf die beiden Listen das Reißverschlussverfahren an ("Z" kommt vom englischen
Wort für Reißverschluss, "zipper") und weist so jeder Kartenfarbe im
Hash eine Bildschirmfarbe zu. Die For-Schleifen in Perl6 unterscheiden
sich syntaktisch von Schleifen in Perl5, auf das Schlüsselwort for
folgt zunächst eine Liste oder ein Array, danach ein Pfeil-Operator und
dann der Name der Variable, die den aktuellen Iterationswert annimmt.
Um das Kartenspiel zu mischen, wendet Zeile 33 einen cleveren Trick mit
dem sogenannten Whatever-Operator *
an: Die Methode pick
auf einen
Array wählt ein willkürliches Element aus, entfernt es aus dem Array
und gibt es zurück. Der Whatever-Operator weist Perl6 an, immer weiter
zu machen, bis der Array leer ist und mischt so den ursprünglichen
Array durch, gibt ihn als Liste zurück, und die Variable auf der linken
Seite der Gleichung erhält die Werte zugewiesen. Die ab Zeile 36 definierte
Methode gleichen Namens entfernt hingegen eine Karte aus dem gemischten
Kartenstapel und gibt sie dem Aufrufer zurück.
Alle Karten, die ein Spieler gerade hält, nennt man auf Englisch eine
"hand", darum implementiert Listing 3 die Klasse Blackjack::Hand.
Die Methode draw()
ab Zeile 9 nimmt ein Objekt vom Typ
Blackjack::Card entgegen und fügt es zum Blatt des Spielers hinzu.
Um den Zählwert (oder besser gesagt die überlagerten Zählwerte)
des Blatts zu ermitteln, addiert die Methode values()
ab Zeile
20 die Zählwerte aller Karten auf. Der kritische Wert von 21
ist überschritten, falls keiner der überlagerten Zustände 21 oder
weniger anzeigt, und die Methode is_busted()
ab Zeile 28 gibt in diesem
Fall einen wahren Wert zurück (von Englisch "busted" für "kaputt").
01 use v6; 02 use strict; 03 use Blackjack::Card; 04 05 class Blackjack::Hand { 06 has @.cards; 07 has $.name; 08 09 method draw( Blackjack::Card $card ) { 10 push self.cards, $card; 11 } 12 13 method highval() { 14 my $vals = 15 grep { $_ <= 21 }, self.values; 16 return "BUSTED" if !$vals; 17 return $vals; 18 } 19 20 method values() { 21 my $total = 0; 22 for self.cards -> $card { 23 $total += $card.val; 24 } 25 return $total; 26 } 27 28 method is_busted() { 29 return !( self.values <= 21 ); 30 } 31 32 method Str() { 33 my $str = ""; 34 for self.cards -> $card { 35 $str ~= "-" if $str.chars; 36 $str ~= "$card"; 37 } 38 return "{self.name}: " ~ 39 "$str ({self.highval})"; 40 } 41 42 method is_blackjack() { 43 return self.cards.elems == 2 && 44 self.values == 21; 45 } 46 47 method score( Blackjack::Hand $other ) { 48 return -1 if self.is_busted; 49 return 1 if $other.is_busted; 50 return 0 if self.is_blackjack and 51 $other.is_blackjack; 52 return 1.5 if self.is_blackjack; 53 return -1 if $other.is_blackjack; 54 self.highval > $other.highval ?? 55 return 1 !! 56 return 0; 57 } 58 }
Um das Blatt eines Spielers anzuzeigen, soll es genügen, ein
Objekt der Klasse Blackjack::Hand in einen Stringkontext (also innerhalb
doppelter Anführungszeichen) zu stellen. Das veranlasst Perl6 dazu,
die Methode Str()
des Objekts aufzurufen und deren Rückgabewert
einzusetzen. Die Funktion ab Zeile 32 von Listing 3 iteriert dazu
mit der Methode cards()
durch alle Karten des Spielerblattes,
stellt deren Objekte ihrerseits in Zeile 36 in einen String-Kontext,
und verbindet die Ergebnisse durch Gedankenstriche. Der ab Zeile 38
zurückgereichte String enthält den Namen des Spielers, die Karten
des Blattes, sowie die mittels highval()
ermittelten Spielwerte.
Der Operator zum Verknüpfen von zwei Strings hat sich von einem Punkt (.
)
in Perl5 zu einer Tilde (~
) in Perl6 geändert. Folglich nutzt Zeile 39
~=
, um den rechts stehenden String an den links stehenden anzuhängen.
Hält ein Spieler eine 10-wertige Karte zusammen mit einem As, zählt dies
als sogenannter "Blackjack" und falls der Dealer nicht ebenfalls mit einer solchen
Kombination aufwartet, erhält der Spieler das 1.5fache seines Einsatzes
als Gewinn ausgezahlt. Die Methode is_blackjack()
prüft diese
Kombination ab Zeile 42, indem sie sicherstellt, dass das Blatt genau
aus zwei Karten besteht und einer der überlagerten Zustände genau
21 Augen zählt. Die dem Spieler zustehenden Gewinnpunkte ermittelt später
die Methode score()
ab Zeile 47, die als Argument das Objekt des
Dealerblattes zum Vergleich erwartet. Sie gibt -1
zurück, falls
der Spieler einen "Bust" verursacht hat, egal welche Augenzahl
der Dealer hat. Falls der Dealer "busted", kommt 1
zurück, also
ist der Spieler einen Punkt im Plus. Falls beide einen Blackjack haben,
ist das Ergebnis unentschieden, also kommt 0
zurück, und so weiter.
Zu beachten ist, dass der sogenannte "ternary operator" in Perl5, der
mit ...?...:...
, abhängig von
einem Test, entweder den ersten oder zweiten Ausdruck zurückgibt,
in Perl6 zu ...??...!!...
wird.
01 #!/usr/bin/env perl6-in-docker.sh 02 03 use v6; 04 use lib '/perl6'; 05 use Blackjack::Card; 06 use Blackjack::Hand; 07 use Blackjack::Deck; 08 09 my $TTY = open("/dev/tty"); 10 my $deck = Blackjack::Deck.new; 11 my $total = 0; 12 13 while ( 1 ) { 14 my $dealer = 15 Blackjack::Hand.new( name => "Dealer" ); 16 my $player = 17 Blackjack::Hand.new( name => "Player" ); 18 19 $player.draw( $deck.pick ); 20 $player.draw( $deck.pick ); 21 22 $dealer.draw( $deck.pick ); 23 say "$dealer"; 24 $dealer.draw( $deck.pick ); 25 26 while !$player.is_busted { 27 say "$player"; 28 my $in = 29 prompt-char("Your move (h/s/q):"); 30 say ""; 31 given ( $in ) { 32 when 'q' { exit( 0 ); } 33 when 's' { last; } 34 when 'h' { 35 $player.draw( $deck.pick ); } 36 } 37 } 38 39 while !$player.is_busted and 40 !$dealer.is_busted and 41 $dealer.values < 17 { 42 say "$dealer"; 43 $dealer.draw( $deck.pick ); 44 } 45 46 say "$player"; 47 say "$dealer"; 48 49 my $score = $player.score( $dealer ); 50 $total += $score; 51 52 say "Score: $score"; 53 say "Total: $total\n\n"; 54 } 55 56 sub prompt-char($prompt) { 57 ENTER shell "stty raw -echo min 1"; 58 LEAVE shell "stty sane"; 59 60 print $prompt; 61 my $in = $TTY.read(1).decode; 62 say "\r"; 63 return $in; 64 }
Das steuernde Perlskript des Kommandozeilen-Casinos blackjack.p6
steht in Listing 4 und enthält in seiner ersten Zeile einen Verweis
auf den ausführenden Perl6-Interpreter. Doch wo Perl6 installieren?
Auf perl6.org findet sich ein Tarball, den der abenteuerlustige
Admin selbst kompilieren kann, während hunderte von Warnungen
über den Bildschirm flitzen. Am einfachsten holt der moderne
Linux-Enthusiast sich aber mittels
docker pull rakudo-star
ein Docker-Image mit installiertem Perl6-Rakudo. Um nun ein auf dem Host
liegendes Perl6-Skript im Perl6-Interpreter innerhalb des Docker-Containers
aufzurufen, stellt Listing 4 in seine erste, sogenannte Shebang-Zeile,
den Pfad zum Shell-Skript in Listing 5. Dieses startet den Docker-Container,
definiert einen Mount auf das aktuelle Verzeichnis auf dem Host, das
daraufhin innerhalb des Containers unter "/perl6" sichtbar ist.
Listing 4 fügt deswegen in Zeile 4 einen zusätzlichen Suchpfad
für Module als use lib '/perl6'
ein, damit es ddie Blackjack-Module
in den anderen Listings auch findet.
Da der Linux-Kernel aus Sicherheitsgründen keine Shellskripts als
Shebang-Programme zulässt, nutzt Listing 4 den Helfer
/usr/bin/env
als ausführendes Programm, das seinerseits das
Shellskript aufruft, das akzeptiert der Linux-Kernel
dann.
1 #!/bin/sh 2 3 sudo docker run -v `pwd`:/perl6 -i \ 4 -t ready /usr/bin/perl6 /perl6/$*
Tastatureingaben von der Kommadozeile erfordern es normalerweise, dass der User jede Eingabe mit der Return-Taste abschließt, aber im Spielmodus soll das Blackjack-Skript direkt auf Tastendrücke reagieren. Dazu dient auf Unix-Systemen der Terminal-Modus "Raw", den man allerdings nur während der eigentlichen Eingabe aktivieren sollte, um ihn sofort danach in den normalen "cooked"-Modus zurückzusetzen, denn sonst reagiert das Terminal nicht mehr ordnungsgemäß auf später nach Programmschluss eingetippte Shell-Kommandos.
Deshalb setzt die ab Zeile 56 definierte Funktion prompt-char()
(Perl6 erlaubt nun Gedankenstriche in Funktionsnamen) beim
Eintritt ein Shell-Kommando mittels der Utility stty
ab, um den Raw-Modus
einzuschalten, um ihn beim Verlassen der Routine wieder zu deaktivieren. Perl6
bietet hierzu die Schlüsselwörter ENTER
und LEAVE
, um Aktionen beim
Eintreten und später beim Verlassen einer Funktion auszuführen. Vom vorher
geöffneten Terminal in der Variablen $TTY
liest read(1)
in
prompt-char()
ein Byte und die nachgeschaltete Methode decode()
macht aus
dem eingelesenen Buffer-Byte ein ASCII-Zeichen, das das Skript später mit einem
Buchstaben wie "h" (hit) oder "s" (stand) vergleichen kann.
Perl6 verfügt über ein Switch-Statement, das "given/when" heißt und ab Zeile 31 zum Einsatz kommt, um die Tastatureingabe des Spielers mit vorgegebenen Buchstaben zu vergleichen und die entsprechende Spielsteuerung einzuleiten.
Der Spielfluss in Listing 4 ist relativ selbsterklärend, und wenn man
die zur Implementierung notwendigen Codezeilen vergleicht, kommt Perl6 besser
weg. Auch die fehlenden runden Klammern bei den Einleitungen
zu for-
und while-
Schleifen wirken sich positiv auf die Lesbarkeit
aus. Wird sich Perl6 durchsetzen? Es ist vielleicht zu früh um diese
Frage zu beantworten, der Praxistest wird sie entscheiden.
Auf der Konferenz in Orlando setzte Larry Wall
das Gerücht in die Welt, an einem Perl6-Buch zu arbeiten,
ließ aber offen, wie lange es zur Veröffentlichung hin ist oder ob das
Projekt überhaupt irgendwann Früchte tragen wird.
Falls man irgendwelche Lehren aus der Vergangenheit ziehen sollte, dann
die, dass durchaus einige Zeit ins Land ziehen könnte, bis
sich etwas rührt in Larry's privatem Imperium.
Listings zu diesem Artikel: ftp://www.linux-magazin.de/pub/listings/magazin/2016/09/Perl
"Quanten-Casino", Linux-Magazin 12/2003, http://perlmeister.com/snapshots/200312/index.html
"Blackjack Soft 17 Rule", http://www.readybetgo.com/blackjack/strategy/soft-17-rule-2496.html
Schrödingers Katze auf Wikipedia, https://de.wikipedia.org/wiki/Schr%C3%B6dingers_Katze