Syntaktische Neuheiten in Perl 5.20

Seite 2: Postfix-Dereferenzierung, Signaturen

Inhaltsverzeichnis

Änderbare Sigils besitzen selbstredend auch Nachteile. 1994, mit der Ankunft der Referenzen, erwuchsen aus ihnen sogar echte Probleme. Nun konnte eine Array-Element wiederum einen Array enthalten. $array[2] gibt aber nur eine Referenz (Typ und Adresse) zurück, beispielsweise ARRAY(0xfc64c8). Den Inhalt entlockt die passende Dereferenzierung: @{ $array[2] }. ("Gib mir die Inhalte, auf die eine Referenz verweist!") Geübte Perl-Programmierer kommen auch mit kniffligeren Fällen wie

@{ $array[$arrayindex][5]{ $hashkey->[4] }[2] }

zurecht. Nur braucht es eben für einige hin und her wandernde Blicke Zeit, um die passenden Klammern zuzuordnen.

$array[2]->@*  # gesamter Unterarrayinhalt
$array[2]->$#* # Anzahl der Elemente

Solche Ausdrücke umfassen ein Paar Klammern weniger und lassen sich bequem von links nach rechts lesen. Darüber hinaus enthalten sie fast keine neue Syntax. -> bedeutet seit Perl 5: "Tu was mit der Referenz links des Pfeils" und ebenso steht @ und $# für das Gleiche wie bisher. Einzig neu ist der Stern – in Perl 6 der "Whatever"-Operator, der oft für "Gib mir alles" steht.

Wenn nicht alle Werte, sondern nur ein Ausschnitt (slice) benötigt wird:

$array[2][7];          # ein Wert, wie bekannt
$array[2]->[7]; # dasselbe
$array[2]->@[7]; # kein Vorteil durch neue Schreibweise soweit
$array[2]->@[5,6]; # 2 Werte, gleichbedeutend mit:
@{$array[2]}[5,6]; # ging bisher nur so
$array[2]->%[5,6]; # auch Pair Slices möglich
$hash{'a'}->%{'g','e'};# bei verschachtelten Hashes entsprechend so

Zusätzlich lassen sich derart Skalar-Referenzen ($), Code-Referenzen (&) und sogar Typeglobs (*) (für direkte Zugriffe auf die Symboltabelle) postfix dereferenzieren, was selbst innerhalb doppelter Anführungszeichen erkannt und evaluiert wird. Besonders Typeglobs sind lediglich für sehr spezielle Einsätze gedacht. Aber ein neues Feature, das alle Möglichkeiten der bisherigen Sprache abdeckt und keine neuen Besonderheiten einführt, zeugt von gutem Sprachdesign.

Das trifft nicht auf das mit Perl 5.14 eingeführte Feature autoderef zu, was den Befehlen push, pop, shift, unshift, splice, keys, values und each erlaubt, selbsttätig zu dereferenzieren. Auch um Perls Verhalten berechenbarer zu gestalten, ist sein geordneter Abgang beschlossen.

Den größten Beifall, aber auch die bissigsten Kommentare erhielt eine Fähigkeit, deren Ankunft ein wenig wie eine Meldung klingt, 2014 habe ein widerspenstiges Bergdorf beschlossen, die Elektrizität einzuführen. Es handelt sich um die in runde Klammern gesetzte Liste der Parameter, die von einer Subroutine/Funktion erwartet werden. Immerhin ist die Gestaltung in Perl 5 durchdacht und enthält etwas mehr, als man erwarten könnte. Dass die "signatures" wie die "postderef" als "experimental" eingeweiht wurden, war reine Vorsicht. Sollten keine schweren Fehler erkennbar werden, wird der Status frühstmöglich aufgehoben, es sei denn, Peter Martini vermag es, getreu seiner Pläne, benannte Parameter und eine Art minimale Typisierung hinzuzufügen. Bis jetzt sind alle Parameter positional und die neuen Signaturen eher ein Weg, @_ nicht anfassen zu müssen – selbst wenn diese Spezialvariable unverändert alle übergebenen Argumente enthält. Ein kleines sinnfreies Beispiel:

use experimental 'signatures';

sub sag ($subjekt, $praedikat, $objekt) {
say "$subjekt $praedikat $objekt.";
}

Neben dem Offensichtlichen tut es zwei Dinge:

  1. Enthielt der Aufruf der Routine sag mehr oder weniger als drei Argumente, so gibt es einen Fehler, wie ihn auch die erzeugt.
  2. Drei Variablen werden lexikalisch lokal (wie mit my) angelegt und mit den Argumenten gefüttert.

Weist man selber in der Signatur einem Parameter einen Default-Wert zu, was ein beliebiger, evaluierbarer Ausdruck sein darf, so deklariert man ihn gleichzeitig zu einem optionalen Parameter.

sub sag ($subjekt, $praedikat, $objekt = held_des_tages()) {

Nun sind auch zwei Argumente akzeptabel. Variadische Funktionen gestatten jedoch unbegrenzt viele Argumente, die ab einer Stelle optional sind.

sub netz_ausgabe ($server, $datei, @zeilen) {

Jetzt müssen es mindestens zwei Argumente sein, nach oben offen. Im Perl 6-Slang heißt der letzte Parameter "slurpy array", weil er quasi alle restlichen Argumente aufschlürft. Dabei ist es Perl egal, ob die Werte beim Aufruf aus Skalaren, Arrays oder Hashes kamen, solange nicht explizit Referenzen überreicht wurden. Eine besondere Form wäre:

sub diff_anwenden ($datei, %zeilen) {

Denn hierbei wird darauf geachtet, dass %zeilen eine gerade Anzahl an Werten bekommt: Paare aus Zeilennummer und Inhalt.

Es gibt aber auch Fälle, in denen Daten nur übergeben werden, um Schnittstellen zu erfüllen. Der Empfänger könnte sie vor Erhalt wegwerfen, um Speicher zu sparen.

sub sag ($, $praedikat, $objekt, @) {

Die neue Syntax ersetzt natürlich keine Prototypen. Sie wurden erfunden, um die eigenen Routinen mit dem speziellen Verhalten an Parameterauswertung auszustatten, über das sonst nur Kernbefehle verfügen. Heutzutage steckt da mehr Magie drin, als die meisten wissen möchten. Dummerweise setzt man auch Prototypen in runde Klammern, weshalb ihnen bei aktivierten Signaturen ein erklärendes Attribut voranzustellen ist:

sub sag :prototype($$;$) ($subjekt,...) {

Der einfachen Nutzbarkeit wegen gab man den Signaturen nicht allzu viel Intelligenz mit, was die Unannehmlichkeit birgt, bei Methoden das notorische ($self,...) als ersten Parameter selbst einfügen zu müssen oder respektive new ($class,...). Mit Method::Signatures oder der Moose-Erweiterung MooseX::Method::Signatures wäre das nicht nötig – ein direkter Vergleich aber auch reichlich unfair. Diese Module können wesentlich mehr und kopieren beinahe buchstabengetreu die Perl-6-Syntax und -Semantik. Eine Kernfunktion, die nicht mit dem sehr ähnlichen Modul signatures zu verwechseln ist, hat einfach, klar, schnell und leichtgewichtig zu sein.

Über ein Dutzend Module wetteiferten seit Jahren im CPAN um das optimale Maß an Funktion und Schreibaufwand. Signaturen wurden im Gefolge der Moose-OOP ein großes Thema für die Perl-Gemeinde, zu dem sich endlich durch die unermüdliche Agitation und Vorarbeit von Peter Martini und die Implementierung von Andrew "Zefram" Main ein tragfähiger Konsens bildet. Bei der Typisierung zeichnet sich eine ähnliche Entwicklung ab, jedoch weniger druckvoll und noch nicht so weit fortgeschritten.

Die "pair slices" ermöglichte Ruslan Zakirov und 'postderef' war die Arbeit von Father Chrysostomos (Ordensname). Im Bereich der freien Software hängt vieles von der schwer berechenbaren Initiative Einzelner ab. Und dennoch erkannte eine Entwicklerversion von Perl 5.21.x den Unicode-7-Standard bereits zwölf Stunden nach seiner Freigabe. (Perl 5.20 unterstützt Unicode 6.3.)

Mit dem Metaobjektprotokoll dauert es wesentlich länger, da man gerade im zweiten Anlauf bestrebt ist, einen Weg zu gehen, der möglichst wenige Umbauten der Interna verlangt. Moose samt Class::MOP ändert sich seit mehreren Jahren kaum noch. Es hat längst einen Standard für Perl-Programmierer gesetzt, der bereits nach Python (elk), JavaScript (Joose) und Ruby (MooseX) portiert wird. Wie seinerzeit bei den regulären Ausdrücken enthält Moose kaum ein Detail, dass nicht bereits woanders (Lisp, OCaml ...) formuliert wurde. Auch hier popularisierte Perl lediglich eine nützliche und praxistaugliche Abwandlung – vielleicht die beste Nebenerscheinung der in dieser Kultur verbreiteten Experimentierbereitschaft.