Programmieren mit Erlang – Teil 1: Grundlagen

Programmiersprachen gibt es bekanntlich wie Sand am Meer – möglicherweise sogar noch viel mehr. Die meisten davon haben eines gemeinsam: Sie stammen von der Programmiersprache C ab. Abseits dieser hauptsächlich dem imparativen Programmierparadigma zuzuordnenden Sprachen gibt es aber noch eine Menge weiterer Sprachen. Neben diversen esoterischen Programmiersprachen, die wohl allesamt in der Praxis nicht genutzt werden oder ProLog, welches einigen vielleicht im Informatik-Unterricht in der Schule einmal begegnet sein könnte und dem deklarativen Programmierparadigma folgt, gibt es auch noch eine ganze Zahl von funktionalen Programmiersprachen. Während davon der größte Teil wohl nur wenig Anwendung außerhalb von Schulen und Universitäten findet, gibt es hierunter auch eine Programmiersprache, die zwar nur wenige kennen, aber tatsächlich auch von der Wirtschaft verwendet wird. Aber genau deshalb möchten wir diese in dieser kleinen Artikel-Serie vorstellen: Erlang.

Was macht Erlang so besonders, dass es hier vorgestellt wird?
Anders als der Name es vielleicht zunächst vermuten lässt, hat Erlang nichts mit der Stadt in Bayern Franken zu tun, stattdessen wurde die Sprache – laut Wikipedia – nach dem dänischen Mathematiker Agner Krarup Erlang benannt. Da die Sprache in den 80-er Jahren bis heute von der Firma Ericsson (vielen wohl eher durch die Kooperation mit Sony bei der Herstellung von Mobiltelefonen bekannt) entwickelt wurde, kann genauso auch angenommen werden, dass Erlang ganz einfach nur eine Abkürzung für “Ericsson Language” darstellt. Verwendet wird die unter der Mozilla Public License lizensierten Sprache heutzutage u.a. im XMPP-Server ejabberd, in der bekannten App fürs Smartphone WhatsApp oder auch diversen Datenbanken wie CouchDB oder SimpleDB.
Besonders gut geeignet ist Erlang für die Nebenläufige, Verteilte und Parallele Programmierung – doch dazu werden wir erst in einem späteren Teil dieser Serie kommen.

Wie programmiere ich mit Erlang?
Erst einmal langsam. Zunächst einmal wird der Erlang-Compiler benötigt. Den erhält man entweder auf Erlang.org oder – zumindest als Linux-Nutzer – in der Paketverwaltung (unter Ubuntu heißt das entsprechende Paket einfach “erlang”). Mit einem normalen Texteditor kann man nun den Quelltext für sein Programm schreiben (Wie? Geduld bitte – kommt gleich). Die Datei speichert man nun in einem beliebigen Ordner und gibt dieser die Dateiendung “.erl”. Nun startet man eine Konsole und wechselt in das Verzeichnis, in das die .erl-Datei gespeichert wurde und kann nun mittels des Befehls “erl” die Erlang-Konsole (Erlang ist eine Skript-Sprache und wird deshalb über eine Konsole bedient) starten. Nun sollte zunächst einmal die neue Datei kompiliert werden – dies lässt sich mit dem Befehl [erlang]c(dateiname).[/erlang] (Der Dateiname wird hier ohne Endung angegeben. Der Punkt nach der schließenden Klammer ist wichtig, um Erlang mitzuteilen, dass danach der Befehl zu Ende ist.) realisieren.

Und wie sieht es nun mit der Syntax aus?
Los geht es am Besten mit dem, was in jeder Erlang-Datei zwingend angegeben werden muss – am Besten auch gleich am Anfang der Datei:
[erlang]-module(modulname).
-export(Funktionsliste).[/erlang]
Der Modulname sollte bestenfalls dem Dateinamen entsprechen und im Übrigen mit einem kleinen Buchstaben beginnen (d.h. kein Großbuchstabe und keine Zahl als erstes Zeichen). Die Funktionsliste ist eine Liste der Funktionen, die für den Nutzer in der Konsole oder in anderen Erlang-Programmen verwendet werden dürfen. Diese wird nach folgendem Muster erstellt:
[erlang][funktion1/1, funktion2/1(, …)][/erlang]
Die Bedeutung: Zunächst wird der Funktionsname angegeben. Dieser wird gefolgt durch einen Schrägstrich und dann der Anzahl der Parameter der entsprechenden Funktion. Mehrere Funktionen werden mit einem Komma separiert.

Doch kommen wir nun zu unserer ersten Funktion: Eine einfache Funktion sieht in etwa so aus:
[erlang]funktion1(Parameter1, …, ParameterN) -> Anweisung1, Anweisung2, …, AnweisungM.[/erlang]
Das heißt zunächst wird der Funktionsname angegeben, der beliebig lang ist und jedes beliebige Zeichen enthalten kann, jedoch mit einem kleinen Buchstaben beginnen muss. Danach folgt in runden Klammern die übliche Parameterliste (hierzu gleich mehr), wobei dank der schwachen Typisierung von Erlang keine Datentypen angegeben werden müssen. Danach folgt ein Pfeil und dann die Anweisungen, welche ebenfalls mit einem Komma separiert werden. Zuletzt folgt der übliche Punkt, um das Ende der Funktion zu signalisieren.

Parameter können sein:
(1) Zahlen: Sowohl die üblichen Integer (ganze Zahlen, z.B. 5, -20, …), Zahlen eines alternativen Zahlensystems bis zur Basis 36 (z.B. binäre Zahlen: 2#1010001 oder hexadezimale Zahlen: 16#AFFE) wie auch Gleitkommazahlen (z.B. 42.1234, -50.11E12) und ASCII-Codes (z.B. $A für 65).
(2) Atome: Atome sind Konstanten, die üblicherweise keinen anderen Wert als ihren eigenen Namen besitzen. Funktionsnamen und Modulnamen sind im Übrigen auch Atome. Somit beginnen Atome mit einem kleinen Buchstaben und können danach jegliches andere Zeichen enthalten. Alternativ kann ein Atom auch mit je einem Hochkomma begonnen und beendet werden und dazwischen jede mögliche Zeichenfolge enthalten (bspw. ‘Ich bin ein Atom’). Folgende Zeichenfolgen sind jedoch bereits reserviert und dürfen als Atome nicht verwendet werden: after, and, andalso, band, begin, bnot, bor, bsl, bsr, bxor, case, catch, cond, div, end, fun, if, let, not, of, or, orelse, query, receive, rem, try, when, xor.
(3) Tupel: In Tupeln werden eine feste Anzahl an Elementen gespeichert. Die Typen der einzelnen Elemente in einem Tupel müssen jedoch nicht vom selben Typ sein. z.B.: {1234, einAtom}, {anderesAtom, {tupel, 1234}, nocheinAtom}, {}.
(4) Listen: Listen sind Tupel mit dynamischer Anzahl an Elementen – d.h. es können jeder Zeit weitere Elemente eingefügt werden. z.B.: [einAtom, {einTupel, inDerListe}, 1234, 5678], [].
(5) Höhere Funktion: In Erlang können auch Funktionen als Parameter einer anderen Funktion angegeben werden oder Rückgabewert einer anderen Funktion sein. Hierum werden wir uns allerdings erst in einem späteren Artikel kümmern.
(6) Bool’sche Werte: Die aus der Logik bekannten Wahrheitswerte true und false können auch in Erlang verwendet werden.
(7) Variablen: Eine Variable beginnt immer mit einem großen Buchstaben und kann danach weitere Buchstaben (groß und klein), Zahlen und Unterstriche enthalten. Sie kann als Wert jeden der anderen Datentypen bekommen, dieser kann jedoch im Gegensatz zu anderen Programmiersprachen nicht mehr verändert werden, nachdem er einmal gebunden wurde. Eine Ausnahme stellt hierbei die sogenannte anonyme Variable dar (ein einfacher Unterstrich, d.h. _), die sofort beim Binden des Wertes diesen wieder vergisst. Außerdem kann eine Variable mittels “f(Variable).” in der Konsole wieder gelöscht werden.

Anweisungen sind:
(1) Arithmetische Funktionen: Die üblichen verdächtigen arithmetischen Operationen können auch in Erlang verwendet werden – das sind: Addition (+), Subtraktion (-), Multiplikation (*) und Division (/ bzw. “div” für die Ganzzahl-Division sowie “rem” für die Modulo-Operation). Weitere Operationen (Potenzieren, …) sind über das math-Modul von Erlang verfügbar.
(2) Funktionsaufrufe: Funktionen aus demselben Modul werden mit dem Funktionsnamen und der darauffolgenden Parameter-Liste aufgerufen (z.B. funktion1(A, 1234, [eine,liste])). Für Funktionen aus anderen Modulen dagegen wird noch der Modulname der entsprechenden Funktion benötigt und getrennt durch einen Doppelpunkt vor den Funktionsnamen gesetzt (z.B. math:pow(2,5)).
(3) Pattern Matchings: Hiermit können Variablen an einen Wert gebunden werden – dies funktioniert auch mit mehreren Variablen im selben Befehl. Zudem können auch einzelne Elemente von Listen mittels | abgetrennt werden. z.B.:
[erlang]A = 1234 % A bekommt Wert 10
[A,B,C] = [1,2,3] % A bekommt Wert 1, B 2 und C bekommt 3
[A,A,B] = [1,1,2] % A wird hier zwei mal auf den gleichen Wert 1 gebunden und bereitet dadurch keine Probleme
[A,A,B] = [1,2,3] % funktioniert nicht, da A zu 1 und 2 gebunden werden würde
[A,B,C] = [1,2] % funktioniert nicht, da die Listen eine ungleiche Anzahl an Elementen enthalten
[A|B] = [1,2,3] % funktioniet! A wird zu 1 und B zur Restliste [2,3]
[A,B|C] = [1,2] % funktioniert auch! A wird zu 1, B zu 2 und C zur leeren Liste []
{A,B,{C,D},E} = {123, atom, {ein, tupel}, true} % funktioniert ebenso
[A|_] = [1,2,3] % A wird zu 1 und die Restliste vergessen
{A,_,{B,_},_} = {123, atom, {ein, tupel}, true} % funkioniert! A wird zu 123 und B zu ein[/erlang]
(Anm.: Mit dem Prozentzeichen lassen sich Kommentare einleiten.)
(4) Rückgabe: Im Gegensatz zu anderen Programmiersprachen, gibt es in Erlang keine separate Anweisung “return”, um einen Anweisungsblock zu beenden. Rückgabewert einer Funktion ist stets die Auswertung der letzten Anweisung im Anweisungsblock.
(5) Vieles mehr: Dies wird dann im nächsten Teil folgen.

Funktionen können im Übrigen in Erlang auch mehrfache Definitionen haben. Das soll heißen, unterschiedliche Eingaben als Parameter können unterschiedliche Funktionen aufrufen. Dies sieht in etwa so aus:
[erlang]funktion1(Parameter11, …, Parameter1N) -> Anweisungsblock1;
funktion1(Parameter21, …, Parameter2N) -> Anweisungsblock2.[/erlang]
Dies können beliebig viele Funktions-Definitionen sein, die jedoch allesamt die gleiche Anzahl an Parametern aufweisen. Die einzelnen Definitionen werden hierbei jedoch nicht mit einem Punkt separiert, sondern mit einem Semikolon. Natürlich würfelt Erlang hierbei aber nicht aus, welche dieser Funktionen dann ausgeführt wird, sondern führt die erste Funktion auf, deren Parameter-Liste zur Eingabe passt. Somit haben wir also eine erste Möglichkeit, um eine Fallunterscheidung zu realisieren.
Ein einfaches Beispiel wären hier die Fibonacci-Zahlen:
[erlang]-module(fibonacci).
-export([fib/1]).

fib(0) -> 0;
fib(1) -> 1;
fib(N) -> fib(N-1) + fib(N-2).[/erlang]
Nach dem Kompilieren kann man nun in der Erlang-Konsole folgendes eingeben:
[erlang]fibonacci:fib(0).[/erlang] und bekommt von Erlang eine 0 ausgegeben, da die erste Definition zuerst passt. Gibt man dagegen folgendes ein:
[erlang]fibonacci:fib(6).[/erlang] gibt Erlang eine 8 aus, da Erlang nun auf die dritte Definition matcht und rekursiv die Funktion solange aufruft, bis der Parameter 0 oder 1 ist und dann auf eine der ersten beiden Definitionen matcht.

(Randbemerkung: Es können auch zwei Funktionen mit unterschiedlicher Parameterzahl den gleichen Namen haben. Diese werden jedoch als zwei komplett verschiedene Funktionen intepretiert, die letztendlich auch mit dem üblichen Punkt anstatt dem Semikolon getrennt werden müssen. Zudem müssen diese auch im -export-Befehl separat aufgeführt werden (aufgrund unterschiedlicher Parameterzahl), sofern diese für den Nutzer zugänglich sein sollen. Letztendlich sollte dies aber möglichst vermieden werden oder nur bei semantisch äquvalenten Funktionen verwendet werden.)

Wie eben schon zu sehen war, muss in der Konsole immer der Name des jeweiligen Moduls vor den Funktionsnamen geschrieben werden. Wer in der Konsole nun den Rückgabewert der Funktion in einer Variablen speichern will, kann dies wie folgt tun:
[erlang]X = fibonacci:fib(6).[/erlang] X hat nun also den Wert 8 und kann für weitere Befehle verwendet werden.

Unser erstes Erlang-Programm haben wir nun also schon geschrieben. Das ist zwar noch nicht so sonderlich nützlich. In den weiteren Teilen dieser Artikelserie werden wir aber langsam aber allmählich auch auf nützlichere Dinge zu sprechen kommen. Im nächsten Teil geht es dann mit weiteren Sprachkonstrukten in Erlang weiter.

Quelle: Teile dieses Artikels wurden inspiriert von Prof. Schäfers Vorlesung “Programmierparadigmen” an der TU Ilmenau sowie der Dokumentation auf erlang.org.

3 Kommentare
  1. Schön geschrieben! Gefällt mir, auch wenn ich BlitzBasic und C++ bevorzuge ;)

    Antworten
    LaborTec
    23. Juni 2012, 12:50
  2. Ehrlich gesagt, hab ich mir auch zuerst gedacht, Erlang ist ne Sprache, die eigentlich niemand braucht, als mir die in der Uni vorgestellt wurde – immerhin kann ich ja JAVA und PHP, wo ich doch schon lange weiß, wie man da programmiert.
    Als das Programmieren mit Erlang dann aber tatsächlich auch praktischer wurde, hab ich erst die Stärken dieser Sprache entdeckt. So wurde uns in der Uni gezeigt, wie man verteilte oder parallele Programme in Erlang und JAVA schreibt. Und genau da war ich der Meinung, dass Erlang um ein Vielfaches einfacher ist, als die Mainstream-Programmiersprachen. Wie genau das geht, wird ja dann in einem 2. oder 3. Teil dieser Artikelserie noch kommen… ;-)

    Antworten
    Chris
    23. Juni 2012, 13:34

Schreibe einen Kommentar zu Chris Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*