Dieses Posting beginnt eine kurze Reihe mit einer Einführung in die funktionale Sprache Clojure. Clojure ist eine funktionale Sprache für die Java-Plattform, die schon des öfteren durch unser Blog gegeistert ist (zum Beispiel hier). Clojure ist in aktiver Entwicklung und hat schon vor Jahren die für industrielle Projekte nötige Reife erreicht. Ihre Schwestersprache ClojureScript, die nach JavaScript kompiliert wird und so im Browser läuft, hatten wir schon hier und hier behandelt.

In diesem Posting zeigen wir, was Sie für einen einfachen Clojure-Einstieg an Software installieren müssen und wie Sie die ersten Gehversuche machen können.

Übrigens …

Clojure ist auch Thema der Konferenz :clojured, die am 24. Januar in Berlin stattfindet. Sie lässt sich zum Doppelpack mit der BOB 2015 am Tag davor kombinieren!

Handwerkszeug

Es ist zwar möglich, Clojure „ohne alles“ zu verwenden, es ist aber - wie bei allen JVM-Sprachen - sinnvoll, ein Werkzeug zu benutzen, um den Build-Prozess, den Classpath etc. zu verwalten. Manuell macht das nur wenig Spaß. Die meisten Wege zu Clojure führen daher über Leiningen, das viele Aufgaben im Zusammenhang mit der Clojure-Entwicklung automatisiert. Es gibt außerdem zahlreiche IDE- und Editor-Plugins (für Eclipse, IntelliJ, Emacs, Vim). Alle o.g. Plugins kommen auch mit Leiningen-Unterstützung und bieten andere Erleichterungen wie Syntax-Highlighting, Completion usw.

Am einfachsten ist der Einstieg mit der kleinen IDE Nightcode. (Da ist Leinigen gleich schon mit drin.) Nightcode lässt sich in Form eines einzelnen Jar-Files herunterladen. Einfach draufklicken oder starten mit:

java -jar nightcode-0.4.2-standalone.jar

Dann auf New Project klicken, als Projekttyp Console anklicken, einen Namen auswählen (in diesem Posting fp1), und los geht‘s!

Nightcode legt schon ein Verzeichnis mit ein paar Dateien an. Wir arbeiten erstmal in src/fp1/core.clj, die Nightcode schon angelegt hat. Einfach im Projektüberblick links drauf klicken. Es erscheint folgendes kleine Programm:

(ns fp1.core
(:gen-class))

(defn -main
[]
(println "Hello, World!"))

Was das Programm tut, liegt nahe - über dem unteren Fenster gibt es einen Run-Knopf: Draufdrücken, und schon erscheint der erwartete Output. (Das dauert ziemlich lange, weil Nightcode erst einmal eine JVM hochfahren muss. Mit Clojure selbst hat das wenig zu tun.)

Ignorieren wir für die Zwecke dieser Einführung erstmal den ns-Header und schauen uns die Definition von -main an. Clojure verrät sich sofort als Lisp-Dialekt: Zusammengesetzte Formen sind immer von Klammern umschlossen (wobei Clojure neben den Lisp-üblichen runden auch eckige und geschweifte Klammern kennt) und durch Whitespace getrennt. Diese Formen sind in Präfix-Notation; die erste Teilform nach der offenen Klammer sagt also, um was es sich handelt.

Eine defn-Form definiert eine Funktion (hier namens -main - der Bindestrich sorgt dafür, dass Clojure die Java-Standard-main-Methode generiert) ohne Parameter (dafür steht das []), die, wenn sie aufgerufen wird, ihrerseits die eingebaute Funktion println aufruft.

Keine große Sache also, wenn man sich an die vielen Klammern gewöhnt hat. A propos Klammern: Wer noch nie in einem Lisp-Dialekt programmiert hat, mag vielleicht denken, es sei umständlich, die immer zu zählen. Das ist allerdings nicht nötig - wenn der Cursor auf einer Klammer sitzt, zeigt Nightcode (sowie alle anderen Clojure-IDEs) die dazugehörige andere Klammer an. Außerdem benutzen Clojure-Programmierer Einrückung - in einem stark standardisierten Format - um die Struktur des Codes lesbar zu machen. Ein Druck auf die Tab-Taste, und Nightcode rückt die aktuelle Zeile sinnvoll ein.

Fürs Lernen ist die Nightcode-REPL praktisch (REPL steht für „Read-Eval-Print-Loop“), in der wir Ausdrücke eingeben können und sofort das Ergebnis ausgedruckt bekommen. Dazu gibt es über dem unteren Fenster den Knopf Run with REPL - einfach mal draufdrücken und im Fenster (-main) eingeben und auf Return drücken. Das sollte dann etwa so aussehen:

fp1.core=> (-main)
Hello, World!
nil

(-main) ist ein Aufruf der Funktion -main - wenn Clojure diesen auswertet, kommt zunächst die Ausgabe. Außerdem wird auch der Rückgabewert von -main gedruckt, nämlich nil, was soviel heißt wie „nichts“ - es gibt hier keinen sinnvollen Rückgabewert. Versuchen wir ein paar weitere Ausdrücke:

fp1.core=> (+ 23 42)
65
fp1.core=> (+ (* 3 4) 42)
54
fp1.core=> (>= 4 3)
true
fp1.core=> (>= 3 4)
false

Sie sehen - alles in Präfix-Notation und vollständig geklammert, ungewohnt aber leicht zu merken.

Als nächstes legen wir eine Definition an, die einen Wert an einen Namen bindet. Dazu schreiben wir ins obere Editor-Fenster folgendes:

(def pi 3.14159265)

Damit die Definition im REPL-Fenster sichtbar wird, ist es notwendig, neu zu laden. Dazu erstmal im Editor-Fenster Save (wird gern vergessen) und dann über dem REPL-Fenster auf Reload drücken. Nun können wir im REPL-Fenster auf pi zurückgreifen:

fp1.core=> pi
3.14159265

Die Definition von pi können wir benutzen, um eine „richtige“ Funktion zu schreiben, die den Umfang eines Kreises mit bekanntem Radius ausrechnet - und zwar wieder ins Editor-Fenster oben:

(defn circumference
[radius]
(* 2 pi radius))

Diese Funktion hat zwischen den eckigen Klammern den Parameter radius, der im Rumpf vorkommen kann. Nach Save und Reload können wir die Funktion in der REPL aufrufen:

fp1.core=> (circumference 5)
31.4159265

Diese ersten Gehversuche geben hoffentlich schon einen ersten Vorgeschmack auf Clojure und erlauben Ihnen, zumindest einfache mathematische Funktionen selbst zu programmieren. Etwas mehr in die Tiefe steigen wir dann mit einem zukünftigen Blog-Posting ein, das dieses hier fortsetzen wird.

Material

Wer nach einem Buch über Clojure sucht, sollte berücksichtigen, dass die Sprache sich gerade in den letzten Jahren stark weiterentwickelt hat. Darum behandeln viele Bücher hier entscheidende Sprachelemente noch nicht. Am ehestens scheint uns das Clojure Programming empfehlenswert.