Common Lisp ist im Gegensatz zu fast allen anderen Programmiersprachen eine programmierbare Programmiersprache. Darum ist Common Lisp sehr gut für exploratives Programmieren geeignet.
Ein paar Besonderheiten:
Lisp Programme werden durch Lisp Datentypen repräsentiert.
Common Lisp hat eine Top-level-loop in der direkt mit dem Lisp-System interagiert werden kann.
Common Lisp hat einen kleinen Kern von Spezial-Konstrukten.
Bezeichner können beliebige Zeichen enthalten. Beispiel: |Auch dies ist ein Symbol|
mit READ und READ-FROM-STRING kann man Lisp Code einlesen. Beispiel: (READ-FROM-STRING "(+ 1 2)") -> (+ 1 2)
Code kann durch Lisp-Code gebaut werden: (LIST '+ 1 (+ 1 1)) -> (+ 1 2)
mit PPRINT kann man Lisp Code formatiert ausgeben. Beispiel: (PPRINT '(+ 1 2))
mit EVAL kann man Lisp Code ausführen. Beispiel: (EVAL '(+ 1 2)) -> 3
mit COMPILE kann man Lisp Code compilieren. Beispiel: (COMPILE NIL (LAMBDA () (+ 1 2))) -> #<Anonymous Function #x291945E>
mit COMPILE-FILE kann man Lisp-Dateien kompilieren.
der Compiler steht zu jeder Zeit zur Verfügung.
mit LOAD kann mal Lisp-Dateien (Quell-Code und kompilierter Code) zu jeder Zeit einlesen.
mit Deklarationen kann man den Compiler steuern. Beispiel: (DECLARE (OPTIMIZE (SPEED 3) (SPACE 1)))
mit Deklarationen kann man Datentypen angeben. Beispiel: (LAMBDA (i) (DECLARE (INTEGER I)) (THE INTEGER (+ i 1)))
mit Backquote kann man Code-Templates bauen. Beispiel: `(* (sin ,a) (cos ,b))
mit Readmacros kann man die Oberflächen-Syntax verändern. Beispiel: #i( a + b[3] * sin (x) )
mit Macros kann man die Syntax veränden und Seiteneffekte erzeugen. Beispiel: (DEFMACRO sqrt (x) `(EXPT ,x 2))
mit Compiler-Macros können Code-Optimierungen geschrieben werden, die vom Compiler genutzt werden.
das Verhalten zur Lade-, Übersetzungs- und Ausführungszeit kann über EVAL-WHEN gesteuert werden.
die Ausgabe von Objekten kann über PRINT-OBJECT gesteuert werden.
man kann auch Methoden für primitive Datentypen (Zahlen, Zeichen, Zeichenketten, ...) schreiben. Beispiel: (DEFMETHOD plus ((a INTEGER) (b STRING)) (+ a (READ-FROM-STRING b)))
man kann auch Methoden für einzelne Objekte schreiben. (DEFMETHOD times ((a NUMBER) (b (EQL 2))) (+ a a))
Common Lisp unterscheidet zwischen EXECUTE, LOAD- und COMPILE-TIME.
Auch zur Lade- und zur Übersetzungszeit steht jeweils das volle Common Lisp zur Verfügung.
Klassen sind Objekte.
die Metaklasse für Klassen kann angegeben werden.
Klassen können zu jeder Zeit erzeugt und verändert werden. Existierende Objekte passen sich automatisch an.
Generische Funktionen und Methoden sind Objekte.
Die Metaklasse für Funktionen und Methoden kann angegeben werden.
Generische Funktionen und Methoden sind Objekte können zu jeder Zeit erzeugt und verändert werden.
Generische Funktionen gehören nicht zu Klassen und werden ausserhalb von Klassen deklariert.
die Methoden der Generischen Funktionen werden zur Laufzeit zu Effektiven Methoden zusammengebaut. Dafür werden (programmierbare) Methodenkombinationen benutzt.
Common Lisp hat :BEFORE, :AFTER, :AROUND und Primary-Methoden. Andere Methodentypen können deklariert werden.
Sub-Methoden können das Verhalten von Supermethoden ergänzen und umgekehrt.
Common Lisp kann Auskunft geben (Introspection) über Packages, Klassen, Funktionen und andere Objekte.
mit Packages kann man sich eigene Programmiersprachen-Varianten bauen.
Conditions (Exceptions) sind Objekte. Eigene Condition-Klassen können definiert werden. Das Condition-System ist objekt-orientiert.
Fehler können vollständig abgefangen und behoben werden. Der Code kann an der Fehlerstelle fortgesetzt werden.
Common Lisp unterscheidet zwischen Fehler signalisieren, Fehler behandeln und Restarts.
für jedes Lisp-Objekt kann zur Laufzeit der zugehörige Datentyp und die zugehörige Klasse ermittelt werden.