Are all immutable data structures in Elixir persistent? If not, which of them are and which not? Also, how do they compare to the persistent data structures in Clojure?
Yes, most of them are persistent data structures.
For example, Elixir lists are linked lists, and a linked list is a degenerate tree (it has only one branch):
Elixir: list = [1, 2, 3, 4] Tree: 1 -> 2 -> 3 -> 4
Every time you prepend an element to a list, it will share its tail:
Elixir: [0|list] Tree: 0 -> (1 -> 2 -> 3 -> 4)
Elixir's HashSet and HashDict implementations are based on Clojure's persistent data structures and are effectively trees. There is some write up on Joseph's blog.
Maps are also persistent data structures and they are very interesting because their representation change based on the amount of keys. When you have small maps, let's say:
%{:foo => 1, :bar => 2, :baz => 3}
It is represented as:
-------------(:foo, :bar, :baz) | (map, keys, values) | ------(1, 2, 3)
So every time you update one key, we share the "keys" bucket and change only the values bucket. This is very efficient for small maps but once you get to about ~20 keys, in Erlang 18, they change their representation to be based on Hash Array Mapped Tries which is similar to Clojure too.
Note tuples are not persistent though (they represent a contiguous space in memory). Once you change one element in the tuple, a whole new tuple is created. This makes them great for holding and accessing few elements as well as pattern matching on them but you definitely don't want to hold many elements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With