mitp Professional Land of Lisp Lisp-Programmierung einfach lernen und originelle Spiele programmieren von Conrad Barski 1. Auflage Land of Lisp – Barski schnell und portofrei erhältlich bei beck-shop.de DIE FACHBUCHHANDLUNG Thematische Gliederung: Funktionale, logische, parallele und visuelle Programmierung mitp/bhv 2011 Verlag C.H. Beck im Internet: www.beck.de ISBN 978 3 8266 9163 8 Inhaltsverzeichnis: Land of Lisp – Barski Kapitel 1 Der Einstieg in Lisp In diesem Kapitel werden zunächst die verschiedenen Dialekte von Lisp vorgestellt. Danach wird ANSI Common Lisp, der Dialekt, den wir in diesem Buch benutzen, näher behandelt. Schließlich steigen Sie in die Lisp-Programmierung ein, indem Sie CLISP installieren und testen – die Implementierung von ANSI Common Lisp, mit der Sie alle Lisp-Spiele ausführen können, die Sie in diesem Buch erstellen werden! 1.1 Lisp-Dialekte Jede Sprache, die den zentralen Prinzipien von Lisp gehorcht, gilt als Lisp-Dialekt. Da diese Prinzipien so einfach sind, überrascht es nicht, dass inzwischen buchstäblich Hunderte von Lisp-Dialekten entwickelt worden sind. Weil so viele angehende Lisper zu Übungszwecken ihre eigenen Lisp-Dialekte entwickeln, könnten tatsächlich sogar Tausende halbfertiger Lisps in längst vergessenen Verzeichnissen auf Festplatten des ganzen Planeten vor sich hindämmern. Die überwiegende Mehrheit der Lisp Community verwendet jedoch die folgenden zwei Lisps: ANSI Common Lisp (oft abgekürzt als CL) und Scheme. In diesem Buch arbeiten Sie ausschließlich mit ANSI Common Lisp, dem etwas populäreren der beiden Dialekte. Dennoch können Sie das meiste, was Sie in diesem Buch lernen, auch in Scheme einsetzen (obwohl sich die Funktionsnamen in den beiden Dialekten etwas unterscheiden können). 1.1.1 Die Geschichte zweier Lisps Zwischen ANSI Common Lisp und Scheme gibt es einige tiefgreifende philosophische Unterschiede, die verschiedene Programmiererpersönlichkeiten ansprechen. Nachdem Sie mehr über Lisp-Sprachen gelernt haben, können Sie den Dialekt wählen, der Ihnen am ehesten liegt. Es gibt dabei keine richtige oder falsche Wahl. Folgender Persönlichkeitstest soll Ihnen bei Ihrer Entscheidung helfen: 33 Kapitel 1 Der Einstieg in Lisp Wenn Sie A gewählt haben, schätzen Sie die reine Leistungsstärke Ihrer Sprache. Es macht Ihnen nichts aus, wenn die Sprache wegen einiger pragmatischer Kompromisse Ecken und Kanten hat, solange Sie kompakten Code schreiben können. Für Sie ist ANSI Common Lisp die beste Sprache! ANSI Common Lisp stammt direkt von den historischen Lisp-Dialekten ab, die in Millionen Programmiererstunden entwickelt wurden. Dadurch verfügt es über eine unglaublich reichhaltige Funktionalität. Sicher, es enthält einige barocke Funktionsnamen, die durch zahllose historische Unfälle entstanden sind, aber mit diesem Lisp können in den Händen des richtigen Programmierers wahre Wunderwerke entstehen. Haben Sie sich für B entschieden, dann schätzen Sie saubere und elegante Sprachen. Sie interessieren sich eher für fundamentale Programmierprobleme und sind glücklich, wenn Sie sich die Zeit auf einer wunderschönen Wiese vertreiben, über die Schönheit Ihres Codes nachdenken und gelegentlich einen Forschungsaufsatz über Probleme der theoretischen Informatik verfassen können. Scheme ist die Sprache für Sie! Sie wurde Mitte der 1970er Jahre nach verschiedenen grundsätzlichen Überlegungen zum idealen Lisp von Guy L. Steele und Gerald Jay Sussman entwickelt. In Scheme geschriebene Programme sind in der Regel etwas wortreicher, da Schemer mathematisch reinen Code höher schätzen als möglichst kompakte Programme. Sollten Sie C favorisieren, wollen Sie alles: die Leistungsstärke von ANSI CL und die mathematische Schönheit von Scheme. Bis heute erfüllt kein Lisp-Dialekt beide Anforderungen komplett, aber das könnte sich in Zukunft ändern. Eine Sprache, die für Sie geeignet sein könnte (obwohl diese Behauptung in einem Lisp-Buch an ein Sakrileg grenzt), ist Haskell. Sie zählt nicht zu den Lisp-Dialekten, ihre Anhänger folgen jedoch Paradigmen, die von Lispern allgemein geschätzt werden: Sie halten sich an eine einheitliche Syntax, unterstützen native Listen und arbeiten intensiv mit Funktionen höherer Ordnung. Was aber noch wichtiger ist: Haskell ist (sogar stärker noch als Scheme) extrem streng mathematisch ausgelegt, was es dieser Sprache ermöglicht, eine sehr leistungsstarke Funktionalität unter einer blitzsauberen Oberfläche zu verbergen. Haskell ist sozusagen ein Wolf im Schafspelz. Ähnlich wie Lisp ist es eine Sprache, von deren Studium jeder Programmierer profitieren könnte. 1.1.2 Neue, aufstrebende Lisps Wie gesagt, es gibt es noch keinen echten Lisp-Dialekt, der beides in sich vereint: die rohe Kraft und Flexibilität von ANSI Common Lisp und die Eleganz von Scheme. Es tauchen jedoch einige neue Anwärter am Horizont auf, die dieses Ideal in näherer Zukunft erfüllen könnten. Ein vielversprechendes neues Lisp ist Clojure, ein Dialekt, der von Rich Hickey entwickelt wurde. Clojure baut auf der Java-Plattform auf, so dass es von Haus aus zahlreiche ausgereifte Java-Bibliotheken nutzen kann. Außerdem enthält Clojure einige raffinierte, wohldurchdachte Funktionen, die das Multithreaded Programming erleichtern. Dadurch eignet es sich als Werkzeug für die Programmierung der anscheinend allgegenwärtigen Mehrkern-CPUs. Ein anderer interessanter Kandidat ist Arc. Es ist eine echte Lisp-Sprache, die hauptsächlich von Paul Graham, einem bekannten Lisper, entwickelt wird. Arc befindet sich noch in einem frühen Stadium der Entwicklung – und die Meinungen darüber, welche Verbesserungen es im Vergleich zu den anderen Lisps bietet, sind sehr geteilt. Außerdem ist seine 34 1.1 Lisp-Dialekte Entwicklung bis jetzt nur sehr schleppend vorangeschritten. Es wird noch eine Weile dauern, bis man beurteilen kann, ob Arc ein wirklicher Herausforderer sein wird. Im Epilog werden Sie etwas mehr über Arc und Clojure erfahren. 1.1.3 Lisp-Dialekte für Scriptings Zu den Lisp-Dialekten, die für das Scripting genutzt werden, zählen: 쐽 Emacs Lisp – wird für das Scripting innerhalb des beliebten (und insgesamt beeindru- ckenden) Emacs-Texteditors verwendet. 쐽 Guile Scheme – wird in mehreren Open-Source-Anwendungen als Skriptsprache ver- wendet. 쐽 Script-Fu Scheme – wird in dem Bildbearbeitungsprogramm GIMP verwendet. Diese Dialekte sind Ableger älterer Versionen des Hauptzweiges von Lisp. Sie werden normalerweise nicht für die Erstellung eigenständiger Anwendungen eingesetzt, sind jedoch vollwertige Lisp-Dialekte. 1.1.4 ANSI Common Lisp Um Ordnung in die verwirrende Vielzahl von Dialekten der Sprache zu bringen, entwickelten Mitglieder der verschiedenen Lisp Communities 1981 eine Spezifikation für einen neuen Dialekt namens Common Lisp. 1986 wurde diese Sprache nach weiteren Anpassungen zum ANSI-Common-Lisp-Standard erhoben. Viele Entwickler älterer Lisp-Versionen passten ihre Interpreter und Compiler an diesen neuen Standard an, der sich zur beliebtesten Version von Lisp entwickelte und dies bis heute geblieben ist. Anmerkung In diesem Buch bezeichnet der Begriff Common Lisp die Version von Common Lisp, die durch den ANSI-Standard definiert ist. Ein zentrales Designziel von Common Lisp bestand darin, eine Mehrparadigmen-Sprache zu entwickeln. Das bedeutet, dass die Sprache viele verschiedene Programmierstile unterstützen sollte. Wahrscheinlich haben Sie schon von der objektorientierten Programmierung gehört, die in Common Lisp ziemlich elegant realisiert werden kann. Andere Programmierstile, von denen Sie möglicherweise noch nicht gehört haben, sind unter anderem die funktionale Programmierung, die generische Programmierung und die Programmierung Domain-spezifischer Sprachen, die allesamt in Common Lisp gut unterstützt werden. Sie werden jeden dieser und andere Stile in diesem Buch näher kennenlernen. Einige Tipps für das Arbeiten mit Dateien in CLISP Der Einfachheit halber wollen wir annehmen, dass Sie jede Funktion direkt in die REPL eingeben. Beim Durcharbeiten eines Kapitels könnte es jedoch praktischer sein, Ihren Lisp-Code in eine Textdatei zu schreiben, die Befehle aus dieser Datei zu kopieren und sie dann in die REPL zu kopieren. 35 Kapitel 1 Der Einstieg in Lisp Wie bei anderen Programmiersprachen können Sie auch Codedateien komplett in Common Lisp laden, ohne dass Sie die Befehle einzeln in die REPL eingeben müssen. Erstellen Sie beispielsweise eine Datei namens myfile.lisp, die die beiden folgenden Befehle enthält: (print "Diese Datei enthaelt") (print "zwei Befehle, die Text ausgeben.") Speichern Sie myfile.lisp in einem Verzeichnis und starten Sie dann die CLISP-REPL von diesem Verzeichnis aus. Geben Sie nun die folgenden Befehle in die CLISP-REPL ein, um diesen Code zu laden: > (load "myfile.lisp") ;; Datei myfile.lisp wird geladen… "Diese Datei enthaelt" "zwei Befehle, die Text ausgeben." ;; Datei myfile.lisp ist geladen. T ; (1) ; (2) Wie Sie sehen, wird der Code in der Datei ausgeführt, indem beide Textzeilen ausgegeben werden (1) (2). So können Sie den gesamten Code für die Spielbeispiele in diesem Buch in Lisp-Codedateien eingeben, die jeweils die Endung .lisp haben müssen. Dann können Sie die Dateien in einem Schritt in die REPL laden. (Falls Sie sich die Mühe sparen wollen, können Sie alle größeren Beispiele in diesem Buch von http://www.mitp.de/9163 herunterladen. Sie sind bereits in passende Dateien verpackt und können direkt in die REPL geladen werden.) Sie können Common Lisp auch in einer funktionsreichen IDE (Integrated Development Environment; integrierte Entwicklungsumgebung) verwenden. IDEs können normalerweise die Syntax farbig darstellen, bieten problemlosen Zugriff auf die Dokumentation, helfen Ihnen beim Debuggen Ihrer Programme und unterstützen die Programmentwicklung durch andere hilfreiche Funktionen. Die beliebteste IDE anspruchsvoller Lisper ist der Texteditor Emacs, der mit der SLIME-Bibliothek zusammenarbeitet. Mehr über Emacs und SLIME erfahren Sie unter http://www.gnu.org/software/emacs/ bzw. http://common-lisp.net/project/slime/. Beachten Sie, dass es einen gewissen Aufwand erfordert, Emacs zu erlernen. Im Moment sollten Sie sich jedoch darauf konzentrieren, CLISP zu erlernen und nicht Ihre Kräfte zersplittern, indem Sie gleichzeitig versuchen, sich Emacs/SLIME anzueignen. 1.2 Der Einstieg in CLISP Es werden viele großartige Lisp-Compiler angeboten, einer davon bietet sich jedoch besonders für einen leichten Einstieg in Lisp an: CLISP, ein Open Source Common Lisp. CLISP ist einfach zu installieren und läuft unter jedem Betriebssystem. Andere beliebte Lisps sind beispielsweise: Steel Bank Common Lisp (SBCL), ein schnelles Common Lisp, das als etwas schwergewichtiger als CLISP gilt und ebenfalls Open Source ist; Allegro Common Lisp, ein leistungsstarkes kommerzielles Lisp von Franz, Inc.; LispWorks; Clozure CL sowie CMUCL. Mac-Benutzer sollten LispWorks oder Clozure CL in Betracht ziehen, die auf ihren Maschinen leichter installiert werden können. Für unsere Zwecke ist allerdings CLISP die beste Wahl. 36 1.2 Der Einstieg in CLISP Anmerkung Ab Kapitel 12 werden wir einige CLISP-spezifische Anweisungen verwenden, die als nicht standardmäßig gelten. Bis dahin laufen die Beispiele in diesem Buch jedoch mit jeder beliebigen Implementierung von Common Lisp. 1.2.1 CLISP installieren Sie können einen CLISP Installer von http://www.clisp.org herunterladen. Er läuft unter Windows, Mac OS und Linux-Varianten. Auf einem Windows-PC führen Sie einfach ein Installationsprogramm aus. Auf einem Mac sind einige zusätzliche Schritte erforderlich, die auf der Website beschrieben sind. Auf dieser Website gibt es mehrere Möglichkeiten, einen Installer herunterzuladen: 쐽 Auf der rechten Seite finden Sie unter OUR OFFICIAL DISTRIBUTION SITES den Link WIN32. Wenn Sie diesen Link anklicken, erhalten Sie die neueste Version (2.49) von CLISP, mit der auch die Beispiele in diesem Buch getestet wurden. Diese Version erlaubt ohne besondere Anpassungsmaßnahmen keine Eingabe von deutschen Umlauten. 쐽 Auf der linken Seite finden Sie den Link COMMON LISP ON THE WEB. Wenn Sie diesen Link anklicken, kommen Sie auf eine weitere Seite. Klicken Sie dort im Abschnitt COMMON LISP DOCUMENTATION den Link http://www.frank-buss.de/lisp/clisp.html an. Sie kommen auf die Seite BUILDING A WINDOWS CLISP VERSION. Wenn sie dort den Link OFFICIAL CLISP RELEASE FOR WINDOWS anklicken, erhalten Sie eine ältere Version von CLISP (Version 2.38, Stand August 2011), mit der Sie auch deutsche Umlaute in Funktions- und Variablennamen eingeben können. Wir haben uns hier für die neuere Version ohne Umlaute entschieden. Auf einer Debian-basierten Linux-Maschine sollte CLISP bereits in Ihren Standardquellen enthalten sein. Geben Sie einfach apt-get install clisp auf einer Kommandozeile ein – CLISP wird dann automatisch installiert. Bei anderen Linux-Distributionen (Fedora, SUSE usw.) können Sie die Standardpakete verwenden, die unter Linux packages auf der CLISP-Website verzeichnet sind. Erfahrene Linux-Benutzer können CLISP auch aus den Quellen kompilieren. 1.2.2 CLISP ausführen Um CLISP auszuführen, geben Sie clisp in Ihre Kommandozeile ein. Verläuft alles plangemäß, sehen Sie daraufhin folgende Eingabeaufforderung: $ clisp i i i i i i i ooooo o ooooooo 8 8 8 8 8 8 8 8 8 8 8 8 8 8 I I I I I I I 8 I \ `+' / \ `-+-' I / `-__|__-' 8 | 8 ------+------ 8 o ooooo 8oooooo ooo8ooo ooooo ooooo o ooooo o 8 8 8 8 8oooo 8 8 8 8 ooooo 8 37 Kapitel 1 Der Einstieg in Lisp Copyright (c) Bruno Haible, Michael Stoll 1992, 1993 Copyright (c) Bruno Haible, Marcus Daniels 1994-1997 Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998 Copyright (c) Bruno Haible, Sam Steingold 1999-2000 Copyright (c) Sam Steingold, Bruno Haible 2001-2006 [1]> Wie alle Common-Lisp-Umgebungen startet CLISP automatisch in einer sogenannten Read-Eval-Print Loop (Lesen-Auswerten-Ausgeben-Schleife), kurz REPL. Dadurch können Sie sofort mit der Eingabe von Lisp-Code beginnen. Geben Sie probehalber (+ 3 (* 2 4)) ein. Das Ergebnis wird direkt unterhalb des Ausdrucks ausgegeben: [1]> (+ 3 (* 2 4)) 11 Dies zeigt, wie die REPL funktioniert: Sie geben einen Ausdruck ein, dann wertet Lisp den Ausdruck sofort aus und gibt das Ergebnis zurück. Wenn Sie CLISP schließen wollen, geben Sie einfach quit ein. Nachdem CLISP jetzt auf Ihrem Computer läuft, können Sie ein Lisp-Spiel schreiben! 1.3 Was Sie gelernt haben In diesem Kapitel wurden die verschiedenen Dialekte von Lisp sowie die Installation von CLISP behandelt. Dabei haben Sie Folgendes gelernt: 쐽 Es gibt zwei Hauptdialekte von Lisp: Common Lisp und Scheme. Beide haben eine Menge zu bieten, wir konzentrieren uns in diesem Buch jedoch auf Common Lisp. 쐽 Common Lisp ist eine Mehrparadigmen-Sprache, was bedeutet, dass sie viele verschiedene Programmierstile unterstützt. 쐽 CLISP ist eine Common-LispImplementierung, die leicht einzurichten und deshalb hervorragend für Lisp-Novizen geeignet ist. 쐽 Sie können Ihre Lisp-Befehle direkt in die CLISP-REPL eintippen. 38