Hinweis Lane: Habe heute auf Twitter sehr lustig getroffen, auf den ersten Blick einen Thread. Und dann schaute er genauer hin und stellte fest, dass er nicht nur lustig, sondern auch unterhaltsam war. Und da es heute Freitag ist, habe ich beschlossen, dass es sich lohnt, die Ergebnisse mit meinen Kameraden zu teilen :)
Speichern Sie das folgende Programm in /tmp/quine.pl
Illegal division by zero at /tmp/quine.pl line 1.
Führen Sie es mit dem Befehl aus
perl /tmp/quine.pl
und sie wird ihren eigenen Code ausgeben.
"Quake-Tricks" sind in vielen Programmiersprachen recht einfach zu erstellen, wobei ein Syntaxfehler in der Quelle einen Parser dazu veranlasst, einen Fehler auszugeben, der mit dem Quellcode des Programms übereinstimmt. Ich habe
einige dieser Tricks auf Twitter gepostet , darunter die folgenden:
File "quine.py", line 1 File "quine.py", line 1 ^ IndentationError: unexpected indent
Aber die Perlgerste am Anfang dieses Artikels ist ein ganz anderer Trick - das Programm versteht es
richtig .
Und es funktioniert nicht lange, bis es auf den Fehler der Division durch Null stößt. Diese Quine reagiert sehr empfindlich auf die Benennung von Dateien. Beispielsweise funktioniert das Durchlaufen von ./quine.pl nicht.
Diese Fehlermeldung ist also eigentlich das ganze Programm ?!
Dieses Programm verwendet einen Großteil des Perlenstab-Do-What-I-Mean-Parsers.
Das Symbol / hängt stark vom Anwendungskontext ab und kann als Teilungssymbol oder als Beginn eines regulären Ausdrucks angesehen werden. Und selbst kleine Änderungen im Code dieses Programms führen zu einem Fehler beim Parsen der Regelmäßigkeit und nicht zur Codeausführung. In diesem Fall erscheinen beide / Zeichen im Kontext des Operators.
Andere Nicht-Wörterbuch-Teile dieses Programms sind
1.
, die einfach als Zahl und interpretiert werden
.
Das ist ein Verkettungsoperator.
Was bedeuten die Wörter dann?
Wörter in Perl können Namen von Routinen, Methoden, Paketen oder Klassen sein. Oder (im Lazy-Modus) Zeilen ohne Trennzeichen oder vielleicht sogar etwas anderes, das ich vergessen habe!
Perl verwendet auch eine ungewöhnliche Methodenaufrufsyntax namens "
indirekte Objektsyntax ", die folgendermaßen aussieht:
am häufigsten kann man sehen wie
print $filehandle "message"; my $instance = new Class(args);
Für Perl ist jedoch die folgende Syntax vorzuziehen:
$filehandle->print("message"); my $instance = Class->new(args);
In der
Perlobj- Dokumentation heißt es:
Perl verwendet Heuristiken, um diesen Code zu analysieren, basierend auf den ihm bekannten Paketnamen, den im aktuellen Paket vorhandenen Unterprogrammen, den zuvor angetroffenen Wörtern und der Analyse anderer Eingabedaten. Unnötig zu erwähnen, dass Heuristiken zu sehr unerwarteten Ergebnissen führen können!
Wie analysiert er diesen Code?
Auf der rechten Seite beginnen
pl line 1.
als Methodenaufruf analysiert
line->pl(1.)
Dabei ist line der Name des Pakets (der Klasse) und pl die Methode.
In der Mitte werden "at", "tmp" und "quine" als einfache Wörter analysiert, d.h. Saiten. Der Ausdruck wird wie folgt analysiert:
(("at" / "tmp") / "quine") . line->pl(1.)
Links sind zwei gefaltete indirekte Methodenaufrufe:
division->Illegal(zero->by( ... ))
Der zuerst ausgeführte interne Ausdruck lautet:
"at" / "tmp"
Und dies verursacht sofort die Ausnahme durch Division durch Null.