Archive for the 'Common Lisp' Category

Ein Wochenende mit Python

Eher zufällig beschloss ich zu Beginn dieses ausklingenden Wochenendes die Python-Installation [1] auf meinem Rechner etwas näher zu untersuchen. Die Installation von Blender hat zum damaligen Zeitpunkt ein vorinstalliertes Python verlangt. Dann fängt man, sofern Interesse übergesprungen ist, das Googeln an. Gelandet bin ich dann in auf der Dokumentationsseite, genauer gesagt in der Tutorial [2] Sektion. Mittlerweile habe ich da bis Anfang Kapitel 6 (Modules) gelesen. Vieles an Python erinnert mich an Common Lisp, das ich in meinen Versuchen im Herbst 2007 kennen gelernt habe.
Ein Element davon sind die – ich kenne leider nur den englischen Begriff – Keyword Arguments. Verwendet man diese, so ist es egal, in welcher Reihenfolge Parameter an eine Funktion übgergeben werden.

Bsp.: C

void nummer_speichern (char *name, int telefonummer) {}
nummer_speichern („Tux“, 0123456789);
// Spätestens da fängt C an zu meckern
nummer_speichern (0123456789, „Tux“);

Ist in C z.B. eine Funktion mit dem Namen nummer_speichern definiert worden, so muss man beim Aufruf dieser als ersten Parameter den Namen und dann die Telefonummer angeben.

Bsp.: Lisp [3]

 (defun nummer_speichern (&key name telefonummer) ( … ) )
( nummer_speichern :name „Tux“ :telefonummer 0123456789)
( nummer_speichern :telefonummer 0123456789 :name „Tux“)

Mit den Keyword Arguments hat man sozusagen die freie Wahl. In Python muss man, soweit ich es gelesen habe, die Keyword Arguments nicht gesondert einführen bei der Definition der Funktion.

Bsp.: Python [4]

 def nummer_speichern (name, telefonummer):
…
nummer_speichern (name = “Tux“, telefonummer = 0123456789)
nummer_speichern (telefonummer = 0123456789, name = “Tux“)

Was mir ebenfalls sehr vertraut vorkam, waren die Lambda Ausdrücke [5], besser bekannt vielleicht als anonyme Funktionen. Zu meinen Lisp-Zeiten hatte ich zwar nicht viel damit gemacht – irgendwo ist es auch schade, da Lisp durchaus sehr interessante Konzepte hat – aber vergessen habe ich das nicht ganz. Anonyme Funktionen lassen sich dazu verwenden, wenn nur an einer einzigen Stelle schnell mal eine Funktion an eine andere (benannte) Funktion übergeben werden muss.
Und schon steckt man mittendrin in der funktionalen Programmierung, in der Funktionen weitergereicht werden, als wären es gewöhnliche Variablen.
Während der Beschäftigung mit Python verstand ich endlich, was Closures sind. Die deutsche Wikipedia Seite war mir damals bei Lisp – da stieß ich zum aller ersten Mal auf diesen Begriff – keine Hilfe gewesen.

Bsp.: Python

 # multiplikator gibt statt eines Wertes eine vollwertige Funktion zurück
def multiplikator (zahl):
    return lambda x: x * zahl
 
# verdoppeln bekommt x: x*2 zugewiesen
# x ist nun wie ein Parameter von verdoppeln
verdoppeln = multiplikator (2)
verdoppeln(3) # Ergebnis 6

Mittels Zuweisung an verdoppeln habe ich gesorgt, dass die Definition x: x*2 erhalten bleibt. Wikipedia spricht hier von Funktionseinschlüssen, was wohl am ehesten zum Begriff Closure passt. Man kann nicht nur mit Lambda Ausdrücken arbeiten, sondern mit def eine Funktion in der Funktion definieren. (Dazu hat die englische Wikipedia [6] ein schönes Beispiel in Python.)
Was ich zu diesem Python-Wochenende auf jeden Fall sagen kann, ist, dass es sehr aufschlussreich in Sachen funktionaler Programmierung war, obwohl Python auf Wikipedia als mehrparadigmen Sprache bezeichnet wird. Man kann auch entsprechend objektorientiert programmieren – ohne Frage -, jedoch gehöre ich zu den Leuten, die mal abseits der ausgetretenen Pfade wandern.

[1] Python (Wikipedia)
[2] Python 3.x Tutorial
[3] Practical Common Lisp – Functions
[4] Keyword Arguments in Python
[5] Lambda Ausdrücke in Python
[6] Closure (Wikipedia)

SLIME vs. Eclipse

Wenn ich etwas Zeit finde, um mir LISP anzuschauen, dann benutze ich standardmäßig EMACS mit SLIME (Superior Lisp Interaction Mode for Emacs). Ein entsprechendes Plugin für Eclipse habe ich da noch nicht gefunden. Zwar snd einige der Tastenkürzel von EMACS gewöhnungsbedürftig (in Eclipse ist es zum Teil auch nicht besser, wenn vier Tasten gleichzeitig gerdrückt werden wollen (z.B.: Shift-Alt-X-A um ein Applet zu starten)), aber es gibt dennoch so ein paar nette Features. Der Klassiker ist die Textvervollständigung. Dieses ist aber nicht das einzige, was mir so gut gefällt.
Es war der SLIME Inspector, der es mir angetan hatte:

SLIME Inspector

SBCL hat (Speicher-)hunger

Nachdem ich den aktuellen CRE 84 Podcast zum Thema LISP gehört hatte, dachte ich mir: Probier doch mal das SBCL aus, dass ist ja als sehr flott beschrieben worden unter den freiverfügbaren Common LISP Implementationen. Bisher verwende ich CLISP. Entpacken, Verzeichnis aufmachen und das Shell-Script starten. So einfach sollte es gehen, nur machte mir die Hardware einen Strich durch die Rechnung. (Alan (Computer) hat zu wenig RAM)

Stattdessen erscheint dieser Text in Emacs:

mmap: Nicht genügend Hauptspeicher verfügbar
ensure_space: failed to validate 536870912 bytes at 0×09000000
(hint: Try “ulimit -a”; maybe you should increase memory limits.)

Process inferior-lisp exited abnormally with code 1

:( :( :(

Dann bleibe ich eben bei CLISP. Damit lässt sich auch (für den Anfang) gut programmieren.

Immer wieder diese Klammern

Ich komme manchmal ganz schön durcheinander, wenn ich mich in Common Lisp versuche. Ich habe mich gerade einmal durch das Kapitel functions von Practical Common Lisp gewälzt, und daraufhin schön brav meine ersten mehr oder weniger nützlichen Funktionen geschrieben.
Und das sieht dann in etwa so aus (hier: Berechnung der Fibonaccizahlen):

(defun fib (n)
   (if (< n 2)
      (return-from fib n)
          (return-from fib (+ (fib (- n 1)) (fib (- n 2))))))

Äh, die wievielte Klammer war das jetzt? :-? :?: :?: :?:
Dann hilft mir meist nur noch zählen. Sollte was nicht stimmen, wird sich der Lisp-Interpreter eh beschweren. Oh, Mann.