zurück zum Artikel

Perl 6: Ja, ist denn schon Weihnachten?!

| Susanne Schmidt, Dr. Oliver Diedrich

Lange erwartet, viel polemisiert, von vielen schon abgeschrieben, von anderen mit Nostalgie oder Hoffnung verfolgt und von einigen wenigen jetzt endlich implementiert: Mit Rakudo Star ist das erste Perl-6-Release erschienen.

Böse Zungen lästern gern über die Dekade, die "das neue, bessere, schönere Perl" jetzt in der Mache ist. Aber Patrick Michaud arbeitet schon seit geraumer Zeit an Rakudo [1], einer Implementierung der Perl-6-Spezifikation [2], die auf der Parrot Virtual Machine basiert. Mit Rakudo Star hat Michaud jetzt ein "benutzbares Perl 6" veröffentlicht – nach jahrelangem Witzeln, Perl 6 [3] erscheine zu Weihnachten, man wisse nur noch nicht, in welchem Jahr.

Verglichen mit Perl 5 ist Rakudo ein neues, ein anderes Perl; deswegen wird es inzwischen als "neues Mitglied der Perl-Familie" bezeichnet und gilt mehr oder weniger als eigenständige Sprache (lesen Sie dazu auch den Kommentar Endlich Weihnachten [4]).

Für den unschuldigen Außenstehenden sieht Rakudo garantiert noch aus wie ein Perl – schon allein dank der Menge an Sigils und Sonderzeichen, für die Perl berüchtigt ist. Sigils bezeichnen in Rakudo konsistenter ihren Inhalt: % für Hashes, @ für Arrays, $ für Sklare – wie man es aus Perl 5 kennt. Auch die allseits bekannten Spezialvariablen behalten ihre -gils – die meisten haben jetzt sogar Twigils: Aus @INC ist jetzt @*INC geworden.

Dafür wurde unter den weniger lesbaren Spezialvariablen aufgeräumt: Wer use English kennt, wird sich mit $*PID schnell anfreunden können. Auch die altbekannten Funktionen (beziehungsweise Methoden) sind alle noch da: shift, unshift, ord, sort, keys, open, pack – hier gibt es wenig Überraschungen hinsichtlich Existenz und Gebrauch. Neu sind trim und pick und dazu einige Funktionen, die in Perl 5 in List::Utils angesiedelt waren – zip beispielsweise oder any und all.

Viele Entwickler dürften sich aber mehr über benannte Parameter von Funktion und Methoden freuen: Wer @_ nie leiden konnte, kann jetzt einfach

sub mysub ($param, @somearray) { .... }

schreiben. Funktionen heißen auch weiterhin sub, Rakudo versteht aber auch Methoden, weil die Sprache in einem "everything is an object"-Modus benutzt werden kann (aber nicht muss). So ist

method mymethod ($param, @somearray) { .... }

das objektorientierte Äquivalent zu obiger Funktion.

Methoden gehören natürlich zu einer Klasse, verstehen weiterhin $self und enthalten alle Fähigkeiten, die man heute von einer objektorientierten Sprache erwarten kann. In bester Perl-Tradition kommt natürlich einiges an Vereinfachungen, Abkürzungen, mehr Flexibilität und syntaktischem Zucker hinzu: Attribute, die in einer Klasse deklariert werden (has $.name, has $.id, is rw), kommen automatisch mit get/set – das muss man nicht mehr selbst deklarieren – genauso, wie new als Standardkonstruktor jetzt out of the box mitgeliefert wird.

Freunde des strengeren Programmierstils dürfen sich dazu noch über Typen freuen: Rakudo kennt ab sofort Typen wie Str, Num, Int, Date, Float oder den generischen Type Any. Jenseits der mitgelieferten Typen kann man (natürlich) auch eigene Subtypen mit

subset Email of Str where { ... }

definieren und dann einfach als

has Email $.email is rw;

benutzen.

Für weniger anspruchsvolle Entwickler, die einfach nur ein schöneres, netteres Perl wollten, ist der Fall damit im Grunde erledigt: Rakudo hat lang erwartete Weiterentwicklungen und kennt jetzt OO und Typen:

class SomeUser {
has Int $.id is rw;
has $.username is rw;
has @.messages;
  method validate_username() {
say "User exists!" if $.username.lc ~~ /ottohorstmeier/;
}
  method show_messages() {
for @.messages -> $message {
$message.say;
}
}
}

Auf den ersten Blick sieht Rakudo etwas anders aus: Der -> aus Perl 5 etwa ist jetzt wie in vielen anderen Sprachen zu einem Punkt geworden, während in Perl 6 -> dazu dient, in for-Schleifen eine Variable für den Schleifenkörper zuzuweisen. Aber der Gebrauch von Klassen und Methoden und der Aufruf der Builtin-Funktionen/-Methoden ist optional – wer weiter einfach typische Perl-Skripte schreiben will, kann genauso gut

lc($username);

oder

say "Something happened";

schreiben und seinen Code in Module sortieren. Damit erlaubt auch Rakudo das Perl-typische Scripting, den schnellen Einzeiler (perl6 -e) zum Wegwerfen – oder eben aufgeräumte OO-Programme.

Nun wäre Rakudo nicht ein Mitglied der Perl-Familie, wenn das schon alles wäre. Jenseits der Möglichkeit, vollständig objektorientiert und typisiert zu programmieren, bleibt auch Rakudo seiner linguistischen Herkunft treu: Ab sofort sind Grammatiken ein Teil der Sprache.

Dabei handelt es sich um eine spezielle Form einer Klasse, die die Regeln für eine Grammatik enthält (typische Beispiele, die bereits existieren, sind HTML oder JSON) und die ein entsprechendes Objekt erzeugt, an dem die Standard-Grammatikmethode .parse (.parsefile) aufgerufen werden kann:

grammar Name {
rule firstname { \w+ }
rule lastname { \w+ }
rule name { <firstname> <lastname> }
}
my $name = "Susanne Schmidt";
my $result = Name.parse($name, :rule<name>);

Die Regeln in einer Grammatik sind letztlich spezielle Methoden und die Zeile Name.parse($name, :rule<name>) übersetzt sich als "Wende Grammatik Name auf $name mit der Regel name an" – genauso könnte man auch

Name.parse($name, :rule<lastname>)

aufrufen. Rakudo selbst ist als eine Grammatik (STD) definiert, die jeder hernehmen und seine eigene Rakudo-Implementation dagegen validieren kann – oder gleich seine eigene Sprache definieren.

Auch die regulären Ausdrücke sind komplett überarbeitet und erneuert worden. Rakudo versteht zwar weiterhin "klassische" Regex, wie sie Perl 5 enthält, hat aber gleichzeitig neue Ausdrücke entwickelt, die "Rules" heißen. Viel Arbeit wurde in das saubere Handhaben von Unicode investiert: Perl 6 unterscheidet zwischen Char, Byte, Graph und Code. Die bekannte Stärke von Perl 5 – Pattern Matching und das Parsen von Text – hat Rakudo mit der Kombination von Grammatiken, Rules, den entsprechenden Methoden (split, comb, words, grep und so weiter) und der Sorgfalt des Unicode-Supports auf ein neues Niveau gehoben.

Was Computer-Linguisten zur Freude gereicht, ist vielen Entwicklern, die Alltags-Code schreiben, vermutlich gleichgültig – wer große und riesige Projekte handhaben muss, wird sich eher auf Rakudos Fähigkeiten, objektorientierten Code zu schreiben, konzentrieren und regen Gebrauch vom oben erwähnten Typ-System machen.

Rakudos System der objektorientierten Programmierung ist so interessant, dass einige Entwickler die Ideen übernommen und als "Moose" für Perl 5 entwickelt haben. Wer sich also auch in Perl 5 mit "role"- und "traits"-basiertem OO vertraut machen will, kann einfach Moose installieren und loslegen. Das Konzept der Roles und Traits stammt aus der Smalltalk-Welt. Dabei handelt es sich um sogenannte "composable units of behavior" – Module, die mit "does" in eine Klasse eingebunden werden. Roles können selbst keine Objekte erzeugen, sondern werden von der Klasse "konsumiert", während Traits auf Attribute angewandt werden.

Die Idee dahinter ist, Vererbung und den Vererbungsbaum wieder auf die essenzielle, wirklich zur Klasse gehörigen Vererbung zu reduzieren und nicht als Methode des "code reuse" zu verwenden. Alles andere, was in die Kategorie von typischen Hilfsmethoden oder Sonderfällen gehört, implementiert man als Role – alle möglichen Arten der Serialisierung oder Datenkonvertierung oder den einen Spezialfall, der nur selten eintritt. Perls linguistische Wurzeln helfen hier bei der Entscheidung, ob etwas eher eine Klasse oder eine Rolle sein sollte: Wer seine Architektur in "is-a" und "has-a" formuliert und auf ein "does" stößt, weiß, dass er es mit einer Rolle zu tun hat.

Typische Konstrukte sehen dann so aus:

class Feed does Atom { ... }

Atom ist dabei eine Role, die eine Methode toAtom (oder fromAtom) enthält. Da Atom-Feeds sich als Grammatik geradezu aufdrängen und validiert werden können, kann man außerdem noch eine passende Grammatik hinzufügen:

grammar AtomPub { ... }
role Atom is AtomPub { ... }
class Feed does Atom { ... }

Allerdings ist das Konzept der Roles und Traits so flexibel und nur so vage mit Rubys Mixins oder Javas Interfaces verwandt, dass man bisher nicht auf einen Regalmeter Literatur zu "Design Patterns mit Roles" oder "Roles Best Practices" zurückgreifen kann. Was als "guter Stil" gilt, muss sich hier erst in der Moose-, Smalltalk- und Rakudo-Welt entwickeln.

Als weitere Neuerung bringt Rakudo ab sofort ein riesiges Sortiment Operatoren mit, die sich oft sowohl als Funktion/Methode als auch als Operator benutzen lassen – man kennt das Konzept bereits von and (&) oder or (|) in Perl 5 und anderen Sprachen. Andere wiederum kommen nur als Sonderzeichen vor. An Array-Operatoren kennt man ".." natürlich schon – den man ab sofort lazy benutzen kann, um etwas zu schreiben wie

my @numbers = 1 .. *;

Dazu kommen sogenannte "Feeds" (<==, ==>), und weil das noch nicht Operatoren genug sind, gibt es auch noch Hyperoperatoren, Kreuzoperatoren und Reduktionsoperatoren. Weil alle Operatoren letztlich Methoden interner Objekte sind, kann man sich außerdem eigene Operatoren definieren. Das Resultat sind Schreibweisen wie:

my $word = join @syllables;
my $word = [~] @syllables;

my @zipped_list = zip(@even, @odd);
my @zipped_list = @even Z @odd;

Die oben erwähnten Parameter einer Methode sind auch nur die halbe Wahrheit in Rakudo. Rakudo beherrscht nämlich nicht bloß positionierte Parameter, sondern auch benannte (foo: $bar) oder optionale Parameter ($bar, *@list) sowie "Multimethods" – Methoden gleichen Names, aber unterschiedlicher Signatur. Rakudo ruft dann anhand der Signatur die passende Methode auf. Natürlich gibt es auch weiterhin anonyme Subs, die man in Skalaren speichern kann. Rakudo bringt außerdem eine Sammlung interner Methoden mit, beispielsweise die typischen Introspektionsmethoden für Klassen und Objekte. So gibt es beispielsweise .^methods(), aber auch .^attributes() und dergleichen mehr.

Zu guter letzt beherrscht Rakudo natürlich auch das übliche volle Sortiment an Konstrollstrukturen wie if, else, unless – hier gibt es wenig Überraschungen. Im Gegensatz zu Perl 5 gibt es allerdings kein foreach mehr. Dafür stehen for und loop zur Verfügung, die zusammen mit den Operatoren sehr mächtige Schleifenkonstrukte erlauben. Der Schleifenkopf muss auch nicht mehr in () gefasst werden: Mit

for %hash.kv -> $key, $value { ... }

iteriert man über die key-value-Paare des Hashes, die jeweils den beiden Skalare $key und $value zugewiesen werden.

Mehr Infos

Installation

Rakudo basiert auf der Parrot-VM, die das Configure.pl-Skript mitinstallieren kann, wenn man kein Parrot installiert hat (--gen-parrot). Die Installation sollte mit einem einfachen

perl Configure.pl
make; make install

erledigt sein. Das Rakudo-Binary landet dann im aktuellen Pfad – wer es lieber in /usr/local/bin haben möchte, muss bei der letzten Anweisung --prefix übergeben.

Nimmt man all diese neuen Fähigkeiten zusammen und kombiniert sie mit der ohnehin schon immensen Flexibilität von Perl 5, kann man sich leicht ausrechnen, dass man in Rakudo sehr zügig coden kann, weil man auf viele Zuckerguss-Konstrukture zurückgreifen kann und Werkzeuge für anspruchsvolle Konstrukte mitgeliefert kriegt.

Da viele Elemente sowieso aus anderen Sprachen bekannt sind (im Zweifel, weil die sie wiederum seinerzeit von Perl adaptiert haben), sollten sich Entwickler aus verschiedenen Welten gut zurechtfinden. Rakudo erlaubt alle Niveaustufen von Perl-Sprech: Baby-Perl, einfache Skripte, Perl-5-Stil, OO als Zuckerguss, OO für große Projekte, Perl optimiert für Linguisten – für jeden ist eine Variante dabei.

Deswegen erscheint Rakudo zunächst riesig im Umfang und ausgesprochen komplex. Es sei daher ausdrücklich betont, dass man nicht alle Fähigkeiten benutzen muss, sondern kann. Auch weiterhin gilt der alte Brauch des "There's more than one way to do it"; und Rakudo erlaubt und unterstützt dieses Konzept durch den flexbilen Übergang zwischen Blöcken, Listen, Methoden und Operatoren, die jetzt beinahe naht- und grenzenlos ineinandergreifen.

Was Rakudo noch fehlt, ist die volle Bandbreite der CPAN-Module, die es derzeit für Perl 5 gibt; und auch die bereits existierenden Module [5] werden erst in Zukunft über CPAN oder etwas CPAN-ähnliches erhältlich sein – bislang kommen die meisten aus dem GitHub des jeweiligen Entwicklers. Mit dem Projekt blizkost [6] soll man zwar Perl-5-Module in Rakudo laden können, aber für viele Projekte will man sicher früher oder später eine native Implementation. Bisher gibt es eben weder nativen SSL-Support noch vollständiges DBI, keine drei Web-Frameworks oder all jene Netzwerk-Module von SMTP bis DNS, auf die viele Projekte zugreifen.

Auch ist noch eine Menge Geduld gefragt – Rakudo ist noch sehr langsam. Ein paar Fähigkeiten wie Makros oder Threads sind noch gar nicht implementiert. Die Dokumentation ist eher spärlich: Man kann die Spezifikation [7] lesen, die viele Beispiele enthält, es gibt ein paar einschlägige Blog-Einträge und man kann in die Perl 6 Tafeln [8] und das mitgelieferte Mini-Buch gucken. Rakudo wird eine kleine Liste von Modulen mitbringen, aus denen man sich abgucken muss, was sich aus der Spezifikation nicht erschließt.

Für Entwickler, die praktisch sofort mit einem größeren Projekt loslegen wollen oder für Unternehmen, die überlegen, so langsam auf Rakudo umzusteigen, ist auch Rakudo Star noch viel zu früh. Rakudo Star ist ein echtes "Early Adopter"-Release, mit dem sich interessierte Entwickler austoben oder an der Weiterentwicklung von Rakudo teilnehmen können.

(odi [9])


URL dieses Artikels:
https://www.heise.de/-1047299

Links in diesem Artikel:
[1] http://rakudo.org/
[2] http://feather.perl6.nl/syn/
[3] http://perl6.org
[4] https://www.heise.de/meinung/Die-Woche-Endlich-Weihnachten-1048034.html
[5] http://modules.perl6.org/
[6] http://github.com/jnthn/blizkost
[7] http://feather.perl6.nl/syn/
[8] http://wiki.perl-community.de/Wissensbasis/Perl6Tafel
[9] mailto:odi@ix.de