Infixschreibweise für Common-Lisp

Thu, 17 Jul 2008 15:57:02 +0000

Ein sehr großer Kritikpunkt, den man immer wieder von Nicht-Lispern über Lisp hört, ist der Mangel an einer Infix-Notation. Infix-Notationen und sonstiger Syntaktischer Zucker machen einen Parser zwar komplizierter, aber können scheinbar den Code lesbarer machen(wenn man bescheuert ist).

Das sieht man besonders gut an gängigem C-Code, der ja bekanntlich vor Übersichtlichkeit nur so strotzt.

Common Lisp sei jedenfalls eine schlechte Sprache – denn die S-Ausdrücke, die man von Lisp kennt, sind kontraintuitiv. Außerdem hat Lisp keinen syntaktischen Zucker (zumindest habe ich diese Meinung von jemandem gehört, der scheinbar irgendwann dazu gezwungen wurde, Scheme zu lernen – ich rede hier von Common Lisp, nicht von Lisp oder Scheme, und ja, da gibt es einen Unterschied, Lisp ist der Sprachenstamm, und Scheme hat einen Standard, der wohl ungefähr ein zwanzigstel der Länge des Common-Lisp-Standards haben dürfte).

Nun, Common Lisp hat einen Mechanismus, um sich syntaktischen Zucker quasi selbst zu definieren. Diese Technologie wird selten genutzt, ist aber sehr praktisch. Mit ebendieser Technologie (ich benutze bewusst das Wort “Technologie”, da man jeden Web-Schrott inzwischen als “Technologie” bezeichnet) kann man quasi die Syntax von Common Lisp erweitern. Die Technologie nennt sich Reader Macro, also Lesemacro. Wer genaueres wissen will, der lese sich die Dokumentation durch.

Definiert habe ich ein Lesemacro, das an den Character ‘<’ gebunden ist – ich hätte es auch an ‘(‘ binden können, Klammern sind die Standardnotation für Instruktionen unter CL, aber das wollte ich – aus Debugtechnischen Gründen, und weil ich generell gerne auch Instruktionen eingeben können will, die nicht durch mein Macro gehen – nicht, aber ob man nun <anweisung> oder (anweisung) schreibt, ist wohl egal.

Ähnlich wie in SML kann man eine Reihe von Infix-Symbolen definieren, allerdings nicht durch einen speziellen Befehl, sondern, indem man die Symbole in eine Liste *infix-symbols* pusht. Die Präferenz wird – auch anders als in SML – nicht durch eine Zahl bestimmt, sondern dadurch, an welcher Stelle in *infix-symbols* das Symbol steht. Rechtsassoziativität und Linksassoziativität muss man nicht unterscheiden, denn ein Term der Form a + b + c wird nicht, wie man vielleicht erwarten würde, in (+ a (+ b c)) oder (+ (+ a b) c) umgewandelt, sondern in (+ a b c), d.h., das Symbol muss zu einer Funktion passen, die sich selbst um die Assoziativität kümmert – das ist rein Effizienztechnisch sinnvoll, oft kann man so einiges im Vorhinein optimieren.

Nundenn, fangen wir an: Ich befinde mich in einer REPL (“Shell”) von SBCL. Zur Erklärung: Hinter “CL-USER>” steht der Befehl, den ich gerade eingebe, darunter die Ausgabe, z.B. das Ergebnis. Zuerst setze ich mal *infix-table* auf einen einigermaßen sinnvollen Wert (einige Symbole brauch ich erst am Ende dessen, was ich zeigen will):

CL-USER> (setf *infix-symbols* '(DEFUN IF FACT PROGN FORMAT = + - * EXPT))
(DEFUN IF FACT PROGN FORMAT = + - * EXPT)

Sehr schön soweit. Jetzt testen wir mal mein Macro:

CL-USER> < 2 + 2 >
4
CL-USER> < 2 * 5 >
10
CL-USER> < 2 * 3 expt 4 >
162

Wundervoll. Einfache Sachen kriegt er also hin. Auch folgendes geht:

CL-USER> < 2 = 2 >
T
CL-USER> < 2 = 71 >
NIL

T steht in dem Fall für “True”, NIL für “False”. Nun, mein Macro bevorzugt Infixe – heißt, wenn der zweite Ausdruck ein Infix-Symbol ist, dann wird der gesamte Ausdruck als Infix ausgewertet. Wenn nicht, wird der erste Ausdruck wie bei normalen S-Ausdrücken, als Instruktionsname genutzt. Man kann also auch sowas schreiben wie

CL-USER> < expt 2 * 5 2 * 5 >
10000000000

Das wird umgewandelt in (expt (* 5 2) (* 5 2)), da 2 kein Infix-Symbol ist. Diese Syntax ist in jedem Fall uneindeutig – ich bevorzuge im Zweifelsfall eben Infixe, man könnte auch Präfixe im Zweifelsfall bevorzugen, eine Frage des Geschmacks.

Ein noch ersprießlicheres Script kriegt man mit der Format-Anweisung. Format ist ein CL-Adäquat für die C-Funktion printf. Man übergibt ihr zwei Argumente, das erste gibt an, wohin geschrieben wird, das zweite (und die restlichen Argumente, die sind jetzt aber erstmal unwichtig), was geschrieben wird. T als zweites Argument steht für den Standard-Output.

CL-USER> (format t "Hallo Welt")
Hallo Welt
NIL
CL-USER> < t format "Hallo Welt infixed" >
Hallo Welt infixed
NIL

Na, da staunt man… stderr sprintf “Hallo Welt infixed”; kann man in C nicht schreiben… Genausowenig kann man überhaupt neue Infixe definieren – dass man wenigstens die vorhandenen Infixe überladen kann, ist eine Neuerung gewesen in C++. Dabei sind doch Infixe so intuitiv. Doch es geht noch weiter. Die Funktion “defun” wird unter CL dazu benutzt, funktionen zu definieren. Wir können eine rekursive Fakultätsfunktion wie folgt definieren:

CL-USER> (defun fact (n) (if (= n 0) 1 (* n (fact (- n 1)))))
FACT
CL-USER> (fact 5)
120

Iiiiiegitt. Wie hässlich. Präfixschreibweise. Saubere S-Ausdrücke. Nein, sowas kann der IT-Experte nicht ertragen. In Infix-Schreibweise ist das doch viel schöner:

CL-USER> <fact defun (n . nil) defun n = 0 if 1 if n * <fact n - 1 > >
FACT
CL-USER> < fact 5 >
120

Mein Beitrag zur Übersichtlichkeit. Wer den Code haben will -> melden.

Den sich wundernden C++-Kundigen Informatiker, weise ich nochmals darauf hin: Diese gesamte Syntax-Struktur wurde von mir selbst definiert. Dazu musste ich nicht den Compiler patchen, sondern es reichte, die Reader-Macro-Facilities zu benutzen (heißt, ein paar Zeilen mehr eintippen, als ich hier Gepostet habe). Man kann damit auch andere lustige Sachen machen – wie gesagt, man kann, wenn man sich genug Mühe gibt, nahezu beliebige neue Syntaxstrukturen definieren. Das ist nur selten wirklich sinnvoll, aber es gibt Situationen. Außerdem macht es die Sprache erweiterbar, und damit um einiges “Mächtiger”, als C und C++, und das ohne relevante Kosten im Sinne von Laufzeit – im Gegenteil, die Compilierzeit kann sich in Extremfällen ein wenig verlängern (was daran liegt, dass ich das Macro nicht sehr efficient geschrieben habe, war mir egal), zur Laufzeit kann man damit aber sogar Vorteile herausholen, eventuell (wobei sich dazu wohl eher die Technologie der Compiler Macros benutzen lässt, auch etwas, was C nur in Spuren hat). Man gibt hier außerdem nicht Code in Form von Strings zurück, sondern in Form von “Forms”, vereinfacht ausgedrückt sind das Listen, die den Code repräsentieren.

Meiner Meinung nach ist diese Technologie zumindest in etwas abgeschwächter, hässlicherer und unsicherer, bzw. hässliche nichtssagende Compilierfehler produzierenden Form, theoretisch auch in C zugänglich, wenn man den Compiler entsprechend erweitern würde – Lesemacros brauchen ja nicht unbedingt starke Optimierung bei der Compilierung. Und meiner Meinung nach würde sie C oder wenigstens C++ auch garnicht unbedingt schaden. Vor Allem aber bei sämtlichen Scriptsprachen, bei denen so ein Mechanismus eigentlich relativ trivial implementierbar sein müsste, zum Beispiel das relativ aufgeschlossene Perl frage ich mich, warum sie nicht soetwas implementieren.


“Gangsta Rap”

Thu, 17 Jul 2008 14:58:10 +0000

Ich persönlich konnte ja mit der gesamten “Black Music” Szene, im Sinne von Gospeln, Jazz und Hip Hop (das gehört meines Wissens alles zu diesem Begriff – vielleicht habe ich den Begriff auch missverstanden, dann bitte Kommentieren – meinen tue ich die Musik, die man überwiegend mit Klischees über farbige Menschen in verbindung bringt, also eigentlich ein rassistischer Sammelbegriff, aber ich habe ihn nicht erfunden), nie besonders viel anfangen. Nicht, dass es keine Lieder gäbe, die mir gefielen, es gibt nur vergleichsweise wenige. Nunja, Musikgeschmack ist verschieden, und ich hoffe mal, kein Farbiger, der das eventuell liest, fühlt sich deswegen irgendwie angegriffen – immerhin stammen große Teile des modernen Techno und Elektropop von “Farbigen” Personen aus den 80er Jahren, nur dass man diese Musik seltsamerweise nicht dazuzählt, und unter dieser Musik gibt es relativ viel, was mir gefällt.
Was ich aber überhaupt nicht ausstehen kann, ist der moderne deutsche “Gangsta Rap”. Wenn ich mir die amerikanischen “Gangsta Rapper” anschaue, nunja, da sehe ich wenigstens irgendwie meistens etwas, was zusammenpasst, auch wenn es mir nicht gefällt. Es mag daran liegen, dass ich deutsch nativ verstehe, und somit merke, von welchem Schrott die Rapper singen, aber jedenfalls finde ich das irgendwie… Unpassend.
Naja, wie dem auch sei. Wem es gefällt, der möge es hören. Anderen gefällt elektrische Musik nicht, und den Leuten, die gerne damit angeben, dass sie einer höheren Schicht angehören, gefällt das alles nicht, und sie hören ausschließlich Opern oder Chorgesang, aber auch das sei erlaubt.

So wie ich – als “Laie” – es verstanden habe, versuchen die meisten “Gangsta Rapper” in gewisser Weise ein Image zu haben, das sich “gegen das System” streubt. Wikipedia gibt darüber leider keinen weiteren Aufschluss (bzw. ich bin zu faul, mir den ganzen Artikel jetzt durchzulesen), aber ich habe halt den Eindruck. Ein scheinbar sehr bekannter solcher Gangsta-Rapper, dessen Name sogar mir ein Begriff war, scheint Bushido zu sein. Und von ebendiesem Rapper las ich heute sehr überrascht diesen Artikel bei Heise. Erstmal gleich ein tolles Zitat, das bei mir für einen kleinen Lacher gesorgt hat:

Ein Rentner hatte erklärt, er wisse gar nicht, wer oder was Bushido sei und habe auch kein Programm, um Musik aus dem Internet herunterzuladen.

Was für eine Überraschung. Jedenfalls hat Bushido laut Heise die Leute verklagt, die sich – zumindest mutmaßlich – dessen Lieder illegal aus dem Internet heruntergeladen haben, so wie ich das verstehe. Der Gangsta, der – laut Wikipedia – dazu verdonnert wurde, entweder eine Ausbildung zum Maler zu machen, oder ins Gefängnis gekommen wäre, verklagt ein paar Leute, weil sie sich seine Musik heruntergeladen haben.

Alda, deine Muddha hat sich meine Songs gezogen! Alles voll Anti! Gegen das System!

Nun, ich bin mir sicher, auch andere “Gangsta” mit Plattenlabel würden sich ähnlich verhalten, vielleicht würden die ja, um ihr Image zu bewahren, wenigstens anderen Leuten das Verklagen überlassen.

Täusche ich mich, oder befindet sich in dieser Situation eine gewisse Ironie?


Follow

Bekomme jeden neuen Artikel in deinen Posteingang.