John McCarthy
Lisp, entwickelt 1958 von John McCarthy am Massachusetts Institute of Technology (MIT), ist eine der ältesten Programmiersprachen und basiert auf der rekursiven Funktionstheorie. Lisp wurde vor allem in der Künstlichen Intelligenz (KI) eingesetzt, mit bekannten Anwendungen wie dem Expertensystem DENDRAL und dem KI-Framework Cyc. Heutzutage ist Lisp immer noch relevant, insbesondere in der Forschung und in spezialisierten Bereichen der Softwareentwicklung. Dialekte wie Common Lisp und Scheme werden weiterhin für ihre Flexibilität und mächtigen Makrosysteme geschätzt, die es ermöglichen, komplexe Programme effizient zu entwickeln und zu erweitern.
Lisp ist eine Skriptsprache, was bedeutet, dass der Code zur Laufzeit interpretiert wird. Du hast zwei Möglichkeiten, Lisp-Code auszuführen:
Möglichkeit 1: Lisp-Code in der CLISP-Shell ausführen
Öffne dazu ein Terminal, indem du entweder StrgJ drückst oder das Panel-Symbol rechts oben drückst. Dein Fenster sollte jetzt ungefähr so aussehen:
Starte nun die CLISP-Shell, indem du clisp
eingibst und dann Enter drückst. Du solltest eine Ausgabe wie diese sehen:
Jetzt kannst du Lisp-Code direkt in der Shell eingeben und ausführen. Schreibe einfach (format t "Hello, world!")
und drücke Enter. Du solltest die Ausgabe Hello, world!
sehen.
Du kannst die CLISP-Shell wieder beenden, indem du (exit)
eingibst und Enter drückst oder einfach StrgD drückst.
Möglichkeit 2: Lisp-Code in einer Textdatei speichern und ausführen
Lisp-Programme werden in Textdateien mit der Endung .lisp
geschrieben. Ein Lisp-Interpreter liest anschließend den Quelltext und führt ihn aus.
Stelle zuerst sicher, dass du keinen Ordner geöffnet hast. Um sicherzugehen, drücke einfach den Shortcut für »Ordner schließen«: StrgK und dann F. Dein Workspace sollte jetzt ungefähr so aussehen:
Klicke auf »New File« und wähle als Dateityp »Text File« (oder bestätige einfach mit Enter).
Schreibe nun den folgenden Code in die Datei:
1 |
(format t "Hello, World!") |
Da Visual Studio Code noch nicht weiß, dass es sich um Lisp-Quelltext handelt, ist dein Programm momentan noch einfarbig, aber das wird sich gleich ändern. An dem weißen Punkt erkennst du, dass deine Änderungen noch nicht gespeichert sind.
Drücke nun StrgS, um die Datei zu speichern. Gib hello.lisp
ein – der vollständige Pfad zu deiner Datei lautet dann /workspace/hello.lisp
.
Da Lisp standardmäßig nicht von Visual Studio Code unterstützt wird, müssen wir noch eine passende Erweiterung installieren. Klicke dazu auf das Erweiterungs-Symbol in der Seitenleiste oder drücke StrgShiftX. Suche nach der Erweiterung »Lisp-Syntax« und installiere sie.
Alternativ kannst du auch StrgP drücken und ext install slbtty.lisp-syntax
eingeben, um die Erweiterung zu installieren.
Anschließend solltest du dein Lisp-Programm farbig sehen:
Um unser Programm auszuführen, müssen wir den Lisp-Interpreter aufrufen (in unserem Fall clisp
) und ihm den Dateinamen unseres Programms übergeben.
Öffne dazu ein Terminal, indem du StrgJ drückst und gib folgenden Befehl ein:
clisp hello.lisp
clisp he
und drücke Tab, um den Dateinamen automatisch zu hello.lisp
vervollständigen zu lassen. Du kannst danach ganz normal weiterschreiben.
Das Programm sollte die Nachricht Hello, World!
im Terminal ausgeben:
Wenn du einen Fehler im Code machst, wird Lisp eine Fehlermeldung ausgeben. Versuche zum Beispiel, statt format
das Wort formt
zu schreiben:
(formt t "Hello, World!"))
Speichere die Datei und führe das Skript erneut aus:
clisp hello.lisp
CLISP sollte eine Fehlermeldung ausgeben, die dir hilft, den Fehler zu finden:
Es lohnt sich, die Fehlermeldungen genau zu lesen, um den Fehler zu finden und zu beheben. Leider gibt CLISP im Gegensatz zu vielen anderen Interpretern keine Zeilennummer an, aber die Meldung sollte dir trotzdem helfen, den Fehler zu finden. Denke daran, den Fehler wieder zu beheben, bevor du das nächste Beispiel ausprobierst.
#!
Bisher musst du, um dein Skript auszuführen, immer den CLISP-Interpreter explizit aufrufen. Wenn du dein Skript wie ein normales Programm ausführen möchtest, kannst du ein sogenanntes Shebang am Anfang deiner Datei hinzufügen. Das Shebang besteht aus einer Raute #
gefolgt von einem Ausrufezeichen !
und dem Pfad zum CLISP-Interpreter. In unserem Fall sieht das so aus:
#!/usr/bin/env clisp
Füge diese Zeile ganz oben in deinem Skript ein und speichere die Datei. Bevor wir das Skript ausführen können, müssen wir es noch ausführbar machen. Das machen wir mit dem Befehl chmod
:
chmod +x hello.lisp
Jetzt können wir das Skript direkt ausführen:
./hello.lisp
Im zweiten Beispiel wollen wir eine Zahl in ihre Primfaktoren zerlegen. An diesem Beispiel kannst du sehen, wie man in Lisp Benutzereingaben verarbeitet und Schleifen verwendet. Erstelle eine neue Datei mit StrgAltN und schreibe den folgenden Code hinein:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
(defun prime-factors (number &optional (return-values '())) ;; function declaration has an optional return-values parameter for ;; tail-recursive use (when (> number 0) ;; no prime factors for negative numbers (loop with max-divisor = (isqrt number) ;; loop through possible divisors ;; stop at divisor = square root of number for divisor = 2 then (if (evenp divisor) ;; if divisor is even, increment ;; if not, add two (1+ divisor) (+ divisor 2)) do (cond ((> divisor max-divisor) ;; have we checked all possible divisors but none fit? ;; number is prime => return with any return-values (return (cons (list number 1) return-values))) ((zerop (rem number divisor)) ;; is number evenly divisible by divisor? ;; we have found a factor of the number. ;; recursively call prime-factors (return (prime-factors ;; use number/divisor as new number (truncate number divisor) ;; add factor to return-values list (or increment ;; counter if more sensible) (if (eq divisor (caar return-values)) (cons (list (caar return-values) (1+ (cadar return-values))) (cdr return-values)) (cons (list divisor 1) return-values))))))))) (format T "Please enter the number to factorise: ") (format T "Prime factors: ~d" (prime-factors (read))) |
Speichere die Datei unter dem Namen factor.lisp
und führe sie aus:
Das Programm hat die Zahl 123 in ihre Primfaktoren zerlegt und ausgegeben. Anders als andere Programmiersprachen kann Lisp auch die Zahl 3000000000 in Sekundenbruchteilen zerlegen. Wenn du allerdings eine sehr große Zahl wie 123456789123456789 verwendest, dauert die Berechnung sehr lange (probier es gern aus, du kannst das Programm mit StrgC abbrechen).
Im dritten Beispiel wollen wir eine Liste von 10 Zufallszahlen sortieren. Dafür verwenden wir den Bubblesort-Algorithmus, der zwar nicht besonders effizient ist, aber sehr einfach zu verstehen und zu implementieren. Der Bubblesort-Algorithmus funktioniert, indem er die Liste mehrmals durchläuft und benachbarte Elemente vertauscht, wenn sie in der falschen Reihenfolge sind.
An diesem Beispiel kannst du sehen, wie man in Lisp Arrays verwendet, Funktionen verwendet und Schleifen verschachtelt.
Erstelle eine neue Datei und schreibe den folgenden Code hinein:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
(defun bubble-sort (sequence &optional (compare #'<)) "sort a sequence (array or list) in place with an optional comparison function (cl:< is the default)" (loop with sorted = nil until sorted do (setf sorted t) ;; assume the list is sorted before checking it (loop for a below (1- (length sequence)) do ;; loop through the sequence (unless (funcall compare ;; use 'compare' function to check seq[a] vs. seq[a+1] (elt sequence a) (elt sequence (1+ a))) ;; if 'compare' function is unfulfilled, rotate [a] and [a+1] (rotatef (elt sequence a) (elt sequence (1+ a))) ;; and of course this means the list is not yet sorted (setf sorted nil))))) (let ((list ;; create a local scope in which 'list' is bound to the following ;; definition (mapcar #'random ;; map the function 'random' to our ten-element list ;; this creates random values between 0 and 100 (make-list 10 :initial-element 100)))) (format t "Original list: ~a~%" list) (bubble-sort list) ;; list is now sorted (format t "Sorted list: ~a~%" list)) |
Speichere das Skript unter dem Namen bubblesort.lisp
und führe es aus:
Das Programm hat eine Liste von 10 Zufallszahlen sortiert. Versuche, den Quelltext so zu verändern, dass statt 10 Zahlen 100 oder mehr Zahlen sortiert werden.
In diesem Kapitel hast du an drei Beispielen gesehen, wie man ein einfaches Lisp-Skript schreiben und ausführen kann. Das ist natürlich nur ein erster Eindruck. Um Lisp wirklich zu beherrschen, musst du noch viel mehr lernen – am besten, indem du eigene Skripte schreibst und ausprobierst. Die Buchhandlungen, Bibliotheken und Youtube sind voll von Material für dich. Viel Spaß beim Programmieren!