Da ich das Glück hatte, an einer halbtägigen Elixir-Schulung teilzunehmen, möchte ich das Thema wieder aufgreifen.
Elixir ist eine relativ neue Programmiersprache, die sich von der Syntax an Ruby anlehnt. Die Programme laufen auf der Erlang-VM (BEAM). Diese VM ist anscheinend restriktiver als die Java-VM und so ist Elixir von den Konzepten her auch sehr nahe an Erlang.
Grundsätzlich ist Elixir wie Erlang eine funktionale Sprache, nicht wie Ruby objektorientiert. Es gibt aber die Möglichkeit, Strukturen aus Listen und Tupeln aufzubauen und weiterzugeben. Alle diese Strukturen sind immutable. Das heißt, dass Änderungen daran stets das Original unverändert lassen und eine Kopie mit den Änderungen generieren. Im Falle von verketteten Listen funktioniert das gut, wenn man nur am Anfang ein Element hinzufügt, weil dann kein eigentliches Kopieren erforderlich ist. Fügt man am Ende etwas hinzu, muss die Liste kopiert werden, was eine aufwändigere Operation ist. Es gibt keine Schleifen, wie in den meisten herkömmlichen Programmiersprachen, sondern man verwendet stattdessen Rekursion. Endrekursion sollte bevorzugt werden, weil das intern in Schleifen umgewandelt wird. Über die Parameterliste dieser Funktion kann man einen „Zustand“ weiterreichen.
Es ist sehr einfach und auch üblich, „Prozesse“ zu generieren. Dies sind nicht OS-Prozesse, sondern Konstrukte innerhalb von Erlang, man kann etwa an Aktoren denken, wie es bei Scala und Akka genannt wird. Wenn genug Hardware-Ressourcen vorhanden sind, kann man ohne weiteres mehrere Millionen solcher „Prozesse“ gleichzeitig haben. Jeder Prozess hat seinen eigenen Speicher und kann jedem anderen Prozess mit
send(...)
Nachrichten (messages) senden. Diese werden in eine sogenannte Mailbox (eine Warteschlange / engl. Queue) des Prozesses eingefügt und von diesem mit
receive(...)
empfangen. Das typische Muster ist, dass ein Prozess mittels Rekursion in einer Endlosschleife ist und jeweils mit receive Messages empfängt und verarbeitet.
Über diese Prozesse kann man doch so etwas wie einen Zustand modellieren. Man hat einfach einen Prozess mit so einer Endlosschleife und schickt ihm „set“- und „get“-Nachrichten. Die „set“-Nachrichten ändern den Zustand, der in der Endlosschleife über die Parameter weitergereicht wird, die get-Nachrichten lösen aus, dass eine Nachricht an den Absender geschickt wird, die dieser wiederum mit receive abfangen muss.
Funktionen mit gleichem Namen werden nach der Anzahl der Parameter, nicht aber nach dem Typ der Parameter, unterschieden. Die Sprache ist dynamisch typisiert. Man kann statt ein großes „if“ innerhalb einer Funktion zu haben, diese auch für verschiedene Fälle definieren und es wird für den tatsächlichen Aufrufparameter die richtige Teildefinition gefunden.