Aus Linux-Magazin 06/2014

Programmieren in Ocaml

© Nudda Chollamark, 123RF

Die Programmiersprache Ocaml gilt als exotisch. Dabei bietet sie neben manchen Eigenheiten insbesondere für Python-, Java- und C-Programmierer Vertrautes. Der Verfasser des Artikels hat den Code seines Open-Source-Projekts auf Ocaml umgestellt und es nicht bereut.

Großen Wert legt die Programmiersprache Ocaml [1] auf Korrektheit und Performance. Ihr statisches Typensystem beispielsweise sorgt dafür, dass die von anderen Sprachen bekannten Segmentation Faults und Null Pointer Exceptions nicht auftreten.

Da Ocaml [2] sich sowohl im funktionalen als auch im imperativen Stil programmieren lässt, eignet sie sich für Entwickler, die von Python, C oder Java kommen und robustere Software schreiben möchten. Der Autor beispielsweise hat seinen plattformübergreifenden Paketmanager Zero Install [3] im Jahr 2013 nach Ocaml portiert (Abbildung 1). Für das Übertragen der 29000 Zeilen Ausgangscode in Python brauchte er sieben Monate und lernte dabei Ocaml.

Abbildung 1: Der Autor hat seinen freien Paketmanager Zero Install von Python nach Ocaml portiert.

Abbildung 1: Der Autor hat seinen freien Paketmanager Zero Install von Python nach Ocaml portiert.

Im Jahr 1996 wurde die Sprache unter dem Namen Objective Caml erstmals veröffentlicht. Sie erweiterte die ältere Programmiersprache Caml um objektorientierte Features. Inzwischen handelt es sich um eine reife, stabile und gut dokumentierte Sprache, deren Implementierung unter den Open-Source-Lizenzen QPL und LGPL steht. Zu den Open-Source-Projekten, die Ocaml einsetzen, gehören der Hypervisor Xen, die Filesharing-Software ML Donkey sowie Coq, ein mathematisches Beweisführungsprogramm.

Die Ocaml-Syntax sieht zunächst ein wenig befremdlich aus. Das folgende Beispiel soll Klärung schaffen (siehe auch den Kasten “Ocaml-Code ausführen”):

let x = 3
let y = 4
let () =
  Printf.printf
    "%d + %d = %d\n"
    x y (x + y)

Ocaml wertet die »let« -Deklarationen der Reihe nach aus und schließt dabei automatisch auf die Datentypen. Ausdrücke, die keinen sinnvollen Rückgabewert liefern, etwa »printf« , geben das leere Tupel »()« zurück, das auch Unit genannt wird und dem »void« in C oder Java ähnelt. Indem der Programmierer das Ergebnis der Unit zuordnet, veranlasst er den Compiler zu prüfen, ob der Ausdruck auch wirklich »()« zurückliefert oder ob der Entwickler vielleicht etwas Wichtiges übersehen hat. »Printf.printf« bezeichnet die Funktion »printf« im Modul »Printf« (Modulnamen beginnen stets mit einem Großbuchstaben). Abbildung 2 zeigt das Ergebnis der Ausführung.

Abbildung 2: Das erste Ocaml-Programm ist schnell ausgeführt.

Abbildung 2: Das erste Ocaml-Programm ist schnell ausgeführt.

Ocaml-Code ausführen

Eine Ocaml-Installation bietet neben Compilern für Bytecode und nativen Binärcode auch einen Interpreter. Um ein Listing auszuführen, speichert man den Code in einer Datei, etwa »prog.ml« , und ruft »ocaml prog.ml« auf.

Ohne Argument startet das Kommando »ocaml« eine interaktive Interpreter-Sitzung. In diesem Modus muss der Anwender am Ende des Codes zwei Strichpunkte (»;;« ) eingeben, um ihn auszuführen.

Funktionen

Das Schlüsselwort »let« kommt auch zum Zuge, um Funktionen zu definieren:

let add x y = x + y

Im Unterschied zu C, Python oder Java setzten Ocmal-Programmierer keine Klammern um die Argumente, auch das Schlüsselwort »return« gibt es nicht. Ocaml wertet den Funktionskörper einfach als einen einzigen Ausdruck aus. Sogar ein If-else-Konstrukt ist solch ein Ausdruck, der einen Wert produziert:

let rec fact n =
  if n = 1 then 1
  else n * fact (n - 1)

Definiert ein Entwickler eine rekursive Funktion, wie hier die Berechnung der Fakultät, verwendet er das Schlüsselwort »rec« , damit die Funktion sich selbst aufrufen kann. Ließe er es weg, wäre der Funktionsname »fact« im Körper nicht sichtbar.

Bitte mit Curry

Ocaml-Funktionen nehmen nur ein einziges Argument entgegen – auch wenn es so aussehen kann, als wären es mehrere. Dahinter steckt das so genannte Currying, die partielle Funktionsanwendung (benannt nach dem amerikanischen Mathematiker Haskell Curry). Dabei nimmt die Funktion das erste Argument an und gibt eine neue Funktion zurück, die das nächste Argument verarbeitet. Das führt dazu, dass die folgenden beiden Ausdrücke äquivalent sind:

add x y
(add x) y

Hier wäre »add 5« eine Funktion, die eine Ganzzahl nimmt und dazu 5 addiert:

let add_five = add 5
let six = add_five 1

Viele Ocaml-Programmierer nutzen die teilweise Funktionsanwendung, um Code kürzer und prägnanter zu schreiben. Die folgenden Zeilen sind gleichbedeutend:

let hi x = printf "Hi, %s!\n" x
let hi = printf "Hi, %s!\n"

In beiden Schreibweisen handelt es sich bei »hi« um eine Funktion mit der Signatur »string -> unit« . Das heißt, sie nimmt eine Zeichenkette und gibt das leere Tupel zurück. Als besonders praktisch erweist sich die partielle Anwendung in Schleifen. So gibt man jedes Element einer Liste aus:

List.iter
  (Printf.printf "- %s\n")
  ["foo"; "bar"]

Das erste Argument für »List.iter« ist die Funktion, die auf jedes Listenelement angewandt werden soll. Teilweise Funktionsanwendung erspart es dem Programmierer in diesem Fall, dafür eine neue Funktion zu definieren.

Funktionen mit Currying erlauben noch weitere praktische Kniffe. Dazu gehört der nützliche Pipe-Operator, den man folgendermaßen als Funktion definieren kann: »let (|>) x f = f x« .

Er nimmt das Argument »x« sowie eine Funktion »f« entgegen und wendet die Funktion auf das Argument an. Was sich zunächst trivial lesen mag, erlaubt eine Schreibweise, die den eingefleischten Linuxer in angenehmer Weise an Shell-Pipelines erinnert:

["foo"; "bar"]
|> List.map String.uppercase
|> List.iter
   (Printf.printf "- %s\n")

Die Funktion »List.map« produziert eine neue Liste, indem sie die angegebene Funktion auf alle Listenelemente der Eingabe anwendet. Der obige Code transformiert die Zeichenketten zuerst in Großbuchstaben und gibt sie dann einzeln auf je einer Zeile aus. Dabei interpretiert Ocaml »x |> f |> g« als »(x |> f) |> g« . Der Pipe-Operator ist in neueren Versionen der Sprache bereits eingebaut.

Ocaml setzt die aus anderen Sprachen bekannte Switch-Verzweigung mittels »match« um:

let to_string x =
  match x with
  | 1 -> "one"
  | 2 -> "two"
  | n -> string_of_int n

Dieser Code schreibt die Zahlen eins und zwei als Wörter auf das Terminal, alle höheren zeigt »string_of_int« als Dezimalzahlen an. Links von den Pipe-Symbolen stehen die Muster, die auf die einzelnen möglichen Fälle passen.

Pattern Matching

Mit diesem so genannten Pattern Matching kann man auf die Übereinstimmung mit Zeichenketten, Datensätzen oder anderen komplexen Datentypen prüfen. Ocaml stellt sicher, dass alle möglichen Fälle abgedeckt sind – eine der Eigenschaften, die die Programmiersprache sicher und zuverlässig machen.

Pattern Matching lässt sich auch in anonymen Funktionen (ähnlich den Lambda-Ausdrücken in Python) einsetzen. Dadurch ergibt sich folgende kompakte Schreibweise:

let to_string = function
  | 1 -> "one"
  | 2 -> "two"
  | n -> string_of_int n

Zu den Datenstrukturen, die der Ocaml-Programmierer selbst definieren darf, zählen Varianten und Records. Varianten, anderswo als Unions bezeichnet, fassen mehrere Möglichkeiten zusammen. Beispielsweise eignet sich eine Variante gut dazu, das Resultat einer Download-Operation zu beschreiben:

type download_result =
  | Success of filepath
  | Network_error of string
  | Aborted_by_user

Der Datentyp »download_result« legt fest, dass jede Stelle im Code, die einen Download vornimmt, mit den drei Möglichkeiten Erfolg, Netzwerkfehler oder Abbruch zurechtkommen muss. Die Anwendung sieht folgendermaßen aus:

match download url with
| Success file -> process file
| Network_error msg -> alert msg
| Aborted_by_user -> ()

Dabei erwartet jeder Fall einen bestimmten Datentyp: einen Dateipfad bei Erfolg, eine Zeichenkette als Fehlermeldung oder eine Unit beim Abbrechen durch den Anwender. Das Programm wird also beispielsweise nicht versuchen eine Datei zu verarbeiten, wenn eine Fehlerbeschreibung als Zeichenkette vorliegt.

Strukturiert

Ein Record, in anderen Sprachen als Struktur bekannt, fasst mehrere Informationen zusammen:

type program = {
  name : string;
  homepage : url option;
}

Records und Varianten lassen sich kombinieren. In den obigen Zeilen steckt im Typ »url option« bereits eine Variante: Das Feld »homepage« kann »None« oder »Some url« enthalten. Mit dieser ausdrücklichen Kennzeichnung optionaler Datentypen weicht Ocaml den Problemen aus, die Java mit Null-Pointern hat und C mit Segmentation Faults.

Daneben unterstützt Ocaml polymorphe (generische) Typen:

type 'a result =
  | Success of 'a
  | Error of exn

Das erlaubt es, eine Typfamilie zu verwenden, die beispielsweise »int result« , »string result« oder »program result« umfasst. Diese kann der Entwickler in generischen Code einsetzen, der für alle Ausprägungen funktioniert:

let success = function
  | Success value -> value
  | Error ex -> raise ex

Die Funktion gibt einen Ergebniswert aus oder wirft die aufgetretene Exception.

Der Programmierer muss Varianten nicht einmal im Vorfeld definieren. Setzt er das Backtick »`« vor einen Bezeichner, versucht der Ocaml-Compiler den Typ automatisch zu ermitteln. Codebeispiele im Artikel werden von dieser Syntax noch Gebrauch machen.

Eine gewöhnungsbedürftige Eigenheit der funktionalen Programmierung besteht darin, Schleifen in einer endrekursiven Form zu schreiben:

let rec ask msg =
  Printf.printf
    "%s [yes/no/abort] " msg;
  match read_line () with
  | "y" | "yes" -> `yes
  | "n" | "no" -> `no
  | "a" | "abort" -> `abort
  | _ -> ask msg

Diese Zeilen stellen dem Anwender eine Auswahlfrage. Tippt er »y« oder »yes« , gibt die Funktion »`yes« zurück, analog in den anderen Fällen. Dabei ist »`yes« der Konstruktor einer Variante, wie zuvor erläutert. Gibt der Benutzer keine gültige Antwort ein, ruft sich die Funktion selbst auf und stellt die Frage erneut. Dieser rekursive Aufruf ist immer das Letzte, was die Funktion tut, daher die Bezeichnung endrekursiv.

Deshalb braucht Ocaml die Rücksprungadresse nicht auf dem Stack zu speichern und kann beliebig oft loopen, ohne dass der Speicher ausgeht. Im Endeffekt wird der Funktionsaufruf so zu einem Goto. Es ist zwar auch möglich, traditionelle For- und While-Schleifen in Ocaml zu schreiben, doch die Rekursion ist stilprägend und gilt als eleganter.

Der folgende Code verwendet die oben definierte Funktion »ask« :

let () =
  match ask "Automatic?" with
  | `yes -> automatic ()
  | `no -> manual ()

Ruft der Anwender sie auf, bemängelt Ocaml, dass das verwendete Pattern nur »`no« und »`yes« berücksichtigt, während die Funktion auch »`abort« als dritte Möglichkeit vorsieht.

Das hat der Programmierer zwar nicht explizit angegeben, doch Ocaml hat diesen Typ automatisch ermittelt. Möchte er Pattern Matching auf das Resultat der Funktion »ask« einsetzen, muss er alle drei möglichen Antworten berücksichtigen. Das könnte er mit einem dritten Fall tun, es geht aber auch anders:

let yes_no msg =
  match ask msg with
  | `yes | `no as x -> x
  | `abort -> exit 0
let () =
  match yes_no "Automatic?" with
  | `yes -> automatic ()
  | `no -> manual ()

Die Funktion »yes_no« bittet mittels »ask« um eine Eingabe. Erhält sie »`yes« oder »`no« , gibt sie diese zurück, »`abort« dagegen bricht das Programm ab. Ocaml weiß in diesem Fall, dass die Funktion nur »`yes« oder »`no« zurückgeben kann. Das passt zu den zwei Patterns in deren Anwendung.

Ocaml-Code kompilieren

In ausführbare Binärdateien lässt sich Ocaml-Code am einfachsten mit dem Kommando »ocamlbuild« übersetzen. Der Programmierer platziert die Quelltextdatei, etwa »prog.ml« , in einem neuen Verzeichnis und ruft Folgendes auf:

ocamlbuild prog.native

Im selben Verzeichnis findet die Konfigurationsdatei »_tags« Platz. Darin kann er beispielsweise alle Compiler-Warnungen aktivieren:

true: warn(A), strict_sequence

In dieser Zeile bedeutet »true:« , dass die Angaben für alle Dateien gelten, »warn(A)« schaltet alle Warnungen ein und »strict_sequence« weist den Compiler an, das Ergebnis aller Funktionen (außer Unit) zu nutzen.

Jede Quelltextdatei mit der Endung ».ml« stellt ein eigenes Ocaml-Modul dar. Funktionen in einem anderen Modul ruft der Programmierer mit der Syntax »Modul.Funktion« auf. Der Modulname beginnt immer mit einem Großbuchstaben, obwohl die entsprechende Datei einen klein geschriebenen Namen führt. Hängt die übersetzte Datei von anderen Modulen im Quelltextverzeichnis ab, kompiliert Ocamlbuild diese automatisch mit.

Päckchenweise

Für Ordnung in umfangreicheren Ocaml-Anwendungen sorgen neben Modulen die so genannten Packages (Pakete), die komplette Tools und Bibliotheken enthalten. Packages lassen sich am einfachsten mit dem Ocaml Package Manager (OPAM) installieren. OPAM ist in den Standard-Paketquellen von Ubuntu beispielsweise nicht enthalten, auf der Homepage [4] finden sich aber eine Installationsanleitung sowie ein Paketarchiv. Um Packages zu installieren, benötigt OPAM zudem die Pakete »Ocaml-findlib« und »build-essential« .

Der Paketmanager ist nicht schwer zu bedienen. Die Befehlszeile

opam install lablgtk

installiert die GTK+-Bindings für eines der folgenden Codebeispiele. Einige Packages lassen sich aber auch über das Paketmanagement der Linux-Distribution einspielen, was manchmal einfacher ist. Um das Package zu benutzen, bearbeitet man wieder die »_tags« -Datei: Folgendes muss in einer einzigen Zeile stehen:

true: warn(A), strict_sequence, package(lablgtk2, lablgtk2.auto-init)

Aus historischen Gründen unterstützt das Buildtool Ocamlbuild in seiner Standardeinstellung keine Packages. Für Abhilfe sorgt aber der Aufruf »ocamlbuild -use-ocamlfind« .

Objekte

Ocaml-Programmierer benutzen Objekte in der Regel zwar kaum, sie können aber insbesondere beim Portieren aus anderen Sprachen praktisch sein. Die Syntax ist etwas ungewöhnlich, denn statt des verbreiteten Punktes trennt ein »#« den Methodenaufruf vom Objekt.

Listing 1 zeigt ein einfaches objektorientiertes GTK+-Programm, in Abbildung 3 ist es in Aktion zu sehen. Die Module »GMain« , »GMisc« und »GWindow« stammen aus der GUI-Bibliothek »lablgtk« , die in der Konfigurationsdatei »_tags« angegeben sein muss. Der Code zeigt die Anwendung so genannter Labels, benannter Parameter wie etwa »~title« in Zeile 7. Das Ende der optionalen Argumente markiert »()« .

Listing 1

GTK+-Dialogbox in Ocaml

01 let (|>) x f = f x     (* (for Ocaml < 4.01) *)
02 let manual () = print_endline "Manual chosen..."
03 let automatic () = print_endline "Automatic chosen..."
04
05 let () =
06   let dialog = GWindow.dialog
07     ~title:"Partitioning"
08     () in
09
10   GMisc.label
11     ~packing:(dialog#vbox#pack ~expand:true)
12     ~text:"Automatic or manual?"
13     () |> ignore;
14
15   dialog#add_button "Cancel" `CANCEL;
16   dialog#add_button "Manual" `MANUAL;
17   dialog#add_button "Automatic" `AUTOMATIC;
18
19   dialog#connect#response ~callback:(function
20     | `AUTOMATIC -> automatic ()
21     | `MANUAL -> manual ()
22     | `CANCEL | `DELETE_EVENT -> GMain.Main.quit ()
23   ) |> ignore;
24
25   dialog#show ();
26   GMain.Main.main ()
Abbildung 3: Ein einfacher GTK+-Dialog in Ocaml.

Abbildung 3: Ein einfacher GTK+-Dialog in Ocaml.

Solcher GUI-Code kann schwer zu testen sein. Der Ocaml-Compiler unterstützt den Programmierer aber mit seiner statischen Typprüfung. Beispielsweise kann er alle möglichen Fälle für die mit »add_button« hinzugefügte Schaltfläche herleiten. Vergisst der Entwickler einen davon zu behandeln, weist ihn eine Fehlermeldung unbarmherzig darauf hin.

Unveränderlich

Ocaml fördert die Verwendung unveränderbarer Datentypen. Listen beispielsweise sind unveränderlich, und so kann der Entwickler sie an mehreren Stellen einer Anwendung einsetzen, ohne dass er Angst vor unerwartenden Änderungen haben müsste. Benötigt er explizit einen veränderbaren Typ, kann er stattdessen ein Array verwenden.

Die Felder eines Record sind standardmäßig nicht änderbar, man kann sie bei Bedarf aber als »mutable« (veränderlich) deklarieren:

type stock_item = {
  id : stock_id;
  mutable location : position;
}

Im Beispiel ist der Ort eines Artikels veränderbar, die ID aber nicht.

Die Bindung eines Werts an einen Namen mittels »let« ist ebenfalls unveränderlich. Wer einen veränderbaren Wert benötigt, muss eine veränderliche Datenstruktur schaffen, die diesen aufnimmt. Ocaml bringt dafür eine eigene Syntax mit:

let total = ref 0 in
for i = 1 to 10 do
  total := !total + i
done;
Printf.printf
  "Total = %d\n" !total

»ref« legt einen neuen Record an, der ein einziges änderbares Feld enthält, das »contents« heißt. Die Schreibweise »!total« liest den aktuellen Wert aus, »:=« setzt einen neuen.

Typfrage

Das Typensystem von Ocaml hat noch mehr zu bieten. Als Beispiel dafür dient das Modul »db.ml« in Listing 2, das eine Bücherdatenbank abfragt. Die passende »_tags« -Datei liefert Listing 3. Die Funktion »search« nimmt ein SQL-Statement entgegen und gibt eine Liste mit den passenden IDs und Titeln zurück. Eine ID kann man wiederum verwenden, um mit der Funktion »author« den Autor zu ermitteln.

Listing 3

Tags-Datei zu db.ml

01 true: strict_sequence, warn(A), thread, package(sqlexpr)
02 <db.ml>: syntax(camlp4o), package(sqlexpr.syntax)

Listing 2

db.ml

01 module Sqlexpr = Sqlexpr_sqlite.Make(Sqlexpr_concurrency.Id)
02
03 let db = Sqlexpr.open_db "books.db"
04 let search = Sqlexpr.select db sqlc"SELECT @d{id}, @s{title} FROM books WHERE title LIKE %s"
05 let author = Sqlexpr.select_one db sqlc"SELECT @s{author} FROM books WHERE id = %d"

Unter Umständen könnte es zu einer Verwechslung der Schnittstellen kommen, und der Programmierer verfüttert vielleicht eine ID aus der falschen Tabelle an eine Funktion. Um ein solches Modul und dessen API zu dokumentieren und Verwechslungen vorzubeugen, bietet Ocaml die Möglichkeit, die Schnittstelle in einer Datei mit der Endung ».mli« zu definieren. Tut der Programmierer das nicht, erschließt der Ocaml-Compiler selber eine. Um die automatisch generierte Variante zu erhalten, eignet sich folgendes Kommando:

ocamlbuild -use-ocamlfind db.inferred.mli

Im Verzeichnis »_build« entsteht bei diesem Schritt die Datei »db.inferred.mli« (Listing 4). Sie enthält die Typen, die Ocaml aufgrund der SQL-Statements erschlossen hat. Die Funktion »search« nimmt einen String als Eingabe entgegen und gibt einen Datentyp zurück, der aus einem Integer für die ID und einer Zeichenkette für den Titel besteht, die Funktion »author« liefert eine Zeichenkette, wenn sie eine Ganzzahl erhält.

Listing 4

db.inferred.mli

01 module Sqlexpr : sig ... end
02 val db : Sqlexpr.db
03 val search :
04   string ->
05   (int * string) list Sqlexpr.result
06 val author : int -> string Sqlexpr.result

Das ist zwar korrekt, aber nicht optimal. Beispielsweise braucht die Schnittstellenbeschreibung nicht den Modulnamen »Sqlexpr« zu enthalten, denn dieser ist ein Implementierungsdetail. Da keine Nebenläufigkeit im Spiel ist, wird auch die Angabe von »Sqlexpr.result« zu einer unnötig genauen Spezifikation.

Mehr Abstraktion

Listing 5 zeigt, um wie viel schlichter und abstrakter eine handgemachte Schnittstellenbeschreibung sein kann: Sie lässt alle irrelevanten Details aus, etwa dass eine SQL-Datenbank im Spiel ist. Daneben führt sie den abstrakten Datentyp »book_id« ein, denn die ID muss nicht in jedem Fall ein Integer sein – auch das ist ein Implementierungsdetail. Als solches kann man es mit der Zeile

Listing 5

db.mli

01 type book_id
02 val search : string -> (book_id * string) list
03 val author : book_id -> string
type book_id = int

in der Datei »db.ml« angeben, um das Beispiel übersetzbar zu machen. Die Datei »db.mli« ist dafür einfacher zu lesen und flexibler einsetzbar.

Beim Programmieren in Ocaml kann sich jeder auch vom Editor helfen lassen. Vim beispielsweise bringt einen Modus für die Sprache bereits mit. Folgende Befehle aktivieren ihn:

:filetype plugin on
:filetype indent on

Außerdem gibt es das Vim-Plugin Syntastic [5], das Syntaxfehler hervorhebt. Noch weiter geht die Software Merlin [6], die mit Vim und auch Emacs zusammenarbeitet. Sie bietet kontextsensitive Vervollständigung und zeigt sogar abgeleitete Typen an.

Resümee

Der Autor hat mit Ocaml positive Erfahrungen gemacht. Im Vergleich zu Python etwa laufen Programme viel schneller und die statische Typprüfung macht den Code robuster. Daneben sichert sie den Programmierer beim Refactoring ab. Die Ocaml-Syntax ist allerdings weniger konsistent, Syntaxfehler lassen sich daher nicht so leicht aufspüren. Verglichen mit Java schreibt sich Ocaml viel kompakter. Daneben sind Anlaufzeit und Speicherverbrauch geringer. Man muss jedoch öfter neu kompilieren.

Ocaml ist leichter zu erlernen als Haskell – eine andere funktionale Programmiersprache –, denn es verwendet vertraute Konstrukte wie While-Schleifen, veränderliche Variablen und Klassen. Das macht vor allem das Portieren leichter. Andererseits bietet Ocaml kein Pendant zu Haskells Typklassen. Daneben stehen für Ocaml viele Bibliotheken zur Verfügung und mit »ocaml-ctypes« kann es C-Code aufrufen. Die Ocaml-Community stellt auf ihrer zentralen Website [1] Tutorials, Bücher und weitere Materialien zur Verfügung (Abbildung 4). Erwähnenswert ist insbesondere das Buch “Real World Ocaml” [7], dessen Inhalt unter Creative-Commons-Lizenz (BY-NC-ND) online verfügbar ist. (mhu)

Abbildung 4: Das ist nicht Perl: Ocaml erhebt Anspruch auf das Kamel als Wappentier.

Abbildung 4: Das ist nicht Perl: Ocaml erhebt Anspruch auf das Kamel als Wappentier.

Infos

  1. Ocaml: http://ocaml.org
  2. Oliver Frommel, “Code-Vehikel”: Linux-Magazin 09/10, S. 48
  3. Zero Install: http://0install.net
  4. OPAM: http://opam.ocamlpro.com
  5. Syntastic: https://github.com/scrooloose/syntastic
  6. Merlin: https://github.com/the-lambda-church/merlin
  7. Yaron Minsky, Anil Madhavapeddy und Jason Hickey, “Real World Ocaml”: https://realworldocaml.org

Der Autor

Der Brite Thomas Leonard hat an der Universität Southampton in Informatik promoviert. Er ist der Hauptentwickler des Paketmanagers Zero Install, über seine Erfahrungen mit Ocaml bloggt er unter http://roscidus.com/blog/.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 6 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
1 Kommentar
Älteste
Neuste Beste Bewertung
AperfectGravity
2 Jahre her

Schade, dass diese Sprache in Deutschland gar nicht bekannt ist. Auf die GitHub OcaML Seite sind fast alle Franzosen und auf Indeed ist nicht mal ein OcaML Job Deutschlandweit.

Nach oben