Alles Immutable: Wie geht das?

Ein radikaler Ansatz, um Multithreading zu vereinfachen, ist es „alles“ immutable zu machen. Man meint, dass das in Java schon recht gut der Fall ist, sind doch Objekte von grundlegenden Klassen wie String, Long, Integer, BigInteger, BigDecimal u.s.w. immutable. Date ist ein bisschen ein Spezialfall, da es fast immer verwendet wird, als wäre es immutable, was aber in Wirklichkeit nicht stimmt.

Aber die Collection-Klassen sind natürlich a priori fast alle mutable. Müssen sie ja sein, weil es z.B. keine vernünftige Schreibweise für eine Map gibt und man sie deshalb sukzessive aufbauen muss. Zwar gibt es die unmodifiable-Wrapper in Collections, aber wenn man Zugriff auf die eingebaute Collection hat, kann man diese immer noch ändern, was zu Überraschungen führen kann.

Die üblichen Collections in Clojure funktionieren anders. Sie sind wirklich immutable. Wenn man also so etwas ähnliches wie ein map.put(k, v) oder map[k]=v in Clojure macht, wird map selber nicht verändert, sondern es wird eine Kopie zurückgegeben, die zusätzlich das neue Paar enthält.

Hier ein Beispiel:

user=> (def x (hash-map 3 4 5 6))
#'user/x
user=> x
{3 4, 5 6}
user=> (def y (assoc x 7 8))
#'user/y
user=> y
{3 4, 5 6, 7 8}
user=> x
{3 4, 5 6}

Man kann sich vorstellen, dass da tatsächlich immer Kopien gemacht werden. Dann würde Clojure natürlich für größere Programme exorbitant Speicher verbrauchen und wäre auch sehr langsam.

Man muss sich eher vorstellen, dass ausgenutzt wird, dass auch die Eingaben immutable sind und dass geschickte interne Datenstrukturen sicherstellen, dass man das Verhalten bekommt, als wäre es kopiert worden, aber intern Optimierungen stattfinden, die mehrfach benutzte Daten gemeinsam nutzen.

Share Button

Schreibe einen Kommentar

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

*