Roles und Signaturen mit Moose: Moderne Erweiterungen für Perl 5

Mit Moose begann eine neue Zeitrechnung für klassenbasierte Objekte in Perl. Doch dank der Spracherweiterung fanden auch Signaturen und Roles (Traits) eine weite Verwendung in Perl-Programmen und sind auch deshalb auf ihrem Weg in den Sprachkern.

In Pocket speichern vorlesen Druckansicht 4 Kommentare lesen
Lesezeit: 16 Min.
Von
  • Herbert Breunung
Inhaltsverzeichnis

Mit Moose begann eine neue Zeitrechnung für klassenbasierte Objekte in Perl. Ein früherer Artikel berichtete, wie es dazu kam, und beschrieb in galaktischen Beispielen die grundlegenden Schreibweisen für Attribute, Methoden, Variablentypen und Vererbung. Doch dank Moose fanden auch Signaturen und Roles (Traits) eine weite Verwendung in Perl-Programmen und sind auch deshalb auf ihrem Weg in den Sprachkern.

Zu Beginn wurde der Elch (engl. Moose) eine Spracherweiterung genannt. Dessen Geweih sollte das Aussehen des guten alten Kamels deutlich ändern. Aber Moose ist mittlerweile vorderster Ausdruck einer Reformbewegung. Das Modul führt die Beliebtheitswertung des MetaCPAN knapp vor dem angesagten Web-Framework Mojolicious an. Auch mit der Anzahl seiner Erweiterungen können sich nur vier von über 25.000 Distributionen messen. Es löst nunmal das drängendste Problem, das Perl 5 hatte. Das ist auch in den 361 Vorschlägen zur Gestaltung von Perl 6 (aus dem Jahr 2000) nachzulesen, von denen sich 35 mit objektorientierter Programmierung befassen, wie etwa die RFC 126.

Doch da die neue Sprachgeneration allerhand Aufgabenstellungen zu lösen trachtet, gab es die Rückportierung der schönen neuen Objekte nur im Verbund mit einigen, bis dahin ungewohnten Konzepten. Dazu gehören merkwürdigerweise Signaturen.

Wenn auswärtige Programmierer zum ersten Mal Perl-Code lesen und dabei beobachten, wie die Argumente jeder Routine einzeln oder komplett aus der Spezialvariable @_ gefischt werden, kann das einen mittelschweren Kulturschock auslösen. Immerhin wurden Signaturen bereits 1958 mit Fortran II eingeführt, waren also selbst 1987 nicht so neumodisch wie diese speicherhungrigen Objekte. Die Perl-Größe Paul Fenwick sagte dazu 2013 in einem Vortrag: "Die Steinzeit rief an und wollte ihre Methoden-Signaturen zurück."

Das Grundproblem ist dem der Perl-5-Objekte ähnlich. Funktional lässt sich alles erreichen – nur mit mehr Wissen und Schreibarbeit als nötig. Referenzen aller Art lassen sich weiterreichen und benannte Parameter durch Hashes simulieren.

sub beschleunigen {
# erster Parameter ist eine Hashref
my $paramter = shift;
say $paramter->{'geschwindigkeit'};
...

Eine Art Signatur steht meist in der zweiten Zeile der Routine.

my ($laenge, $breite, $hoehe) = @_

Und mit dem seit Perl 5.10 (2007) bekannten "defined or"-Operator (//) werden Default-Werte übersichtlich im Routinenkopf angeordnet.

my $msg = shift // 'alternativlos';
my $pos = shift // {20 , 10, 406};

Doch die Tücken beginnen, wenn der nächste Schrägstrich vergessen wird:

beschleunigen(\%parameter);

Dann enthält @_ paarweise alle Schlüssel und Werte des Hash, ununterscheidbar von etwaigen weiteren Parametern. Aber um fair zu bleiben – mit Prototypen lässt sich das verhindern. (Wenn der Aufruf nicht vor der Definition der Routinen erfolgt, was sogar unbemerkt durchgeht, folgt man nicht der besten Praktik, "use warnings;" einzusetzen.)

sub beschleunigen (\%) {
...

Diese runden Klammern umgeben keine Signatur, sondern den sogenannten Prototyp. Er bestimmt, wie viele Argumente beschleunigen erwartet und welchen Perl-Typ sie besitzen müssen (Skalar, Array, Hash, Coderef, beliebige Referenz). Im Beispiel funktioniert dann einzig:

beschleunigen( %parameter );

Zusätzliche oder andere Argumente als eine Hash-Variable lösen einen Compiler-Fehler aus. Innerhalb der Routine enthält @_ eine Hash-Referenz.

Das war eine Masse an Informationen, mit denen sich kein Anfänger belasten mag, der lediglich zwei benannte Parameter braucht. Will er zudem sicherstellen, dass sie eine Zeichenkette und eine natürliche Zahl enthalten, muss er die Überprüfungen selbst schreiben oder wenigstens organisieren, was zweifelsfrei nicht die angepriesene, "perlige" Bequemlichkeit darstellt.

Deswegen schuf Michael G. Schwern (bekannt als Vater wichtiger Testmodule) Method::Signatures, das alle Signaturen-Funktionen von Moose bereitstellt, jedoch wesentlich schneller startet und auch für Programme ohne Objekte nützlich ist. Routinen mit Signaturen nannte Schwern func, damit bestehender Code nicht beeinträchtigt wird. Fast überflüssig zu erwähnen, dass Method::Signatures ebenfalls zu den 100 beliebtesten Modulen gehört.

Peter Martini bereitet derzeit sogar den Interpreter darauf vor, "echte" Signaturen zu unterstützen. Zusammen mit der von Stevan Little wiederaufgenommenen Arbeit an einem Metaobjektprotokoll für Perl 5 ist das nach Einschätzung des Autors die derzeit bedeutendste Entwicklung. Sie hat das Potenzial, weit mehr zu verändern als die letzten drei oder vier Perl-Versionen zusammen. Mit einem MOP im Kern ließen sich die wichtigsten Moose-Funktionen per Pragma (wie strict) mit use zuschalten, und Moose selbst ließe sich spürbar entschlacken und beschleunigen.

Dann fehlt nur noch ein Sprachstandard für eine moderne Ausnahmebehandlung, die sich derzeit mit einem von circa zehn Modulen (zum Beispiel Try::Tiny) nachrüsten lässt. Damit hätte Perl 5 einen Stand erreicht, den sich viele als Perl 6 vorgestellt haben.