Имеет ли Elixir постоянные структуры данных, похожие на Clojure?

Являются ли все неизменные структуры данных в Elixir постоянными? Если нет, то какие из них, а какие нет? Кроме того, как они сравниваются с постоянными структурами данных в Clojure?

Ответы

Ответ 1

Да, большинство из них - постоянные структуры данных.

Например, списки Elixir представляют собой связанные списки, а связанный список - вырожденное дерево (имеет только одну ветвь):

Elixir: list = [1, 2, 3, 4]
Tree:   1 -> 2 -> 3 -> 4

Каждый раз, когда вы добавляете элемент в список, он будет делиться своим хвостом:

Elixir: [0|list]
Tree:   0 -> (1 -> 2 -> 3 -> 4)

Реализации Elixir HashSet и HashDict основаны на стойких структурах данных Clojure и являются фактически деревьями. Есть некоторые записи в блоге Джозефа.

Карты также являются постоянными структурами данных, и они очень интересны, потому что их изменение представления зависит от количества ключей. Когда у вас небольшие карты, скажем:

%{:foo => 1, :bar => 2, :baz => 3}

Он представлен как:

        -------------(:foo, :bar, :baz)
        |
(map, keys, values)
               |
               ------(1, 2, 3)

Поэтому каждый раз, когда вы обновляете один ключ, мы разделяем ведро "ключей" и изменяем только ведро значений. Это очень эффективно для небольших карт, но как только вы доберетесь до ~ 20 ключей, в Erlang 18, они меняют свое представление на основе Hash Array Mapped Tries, который аналогичен до Clojure.

Примечание. Кортежи не повторяются (они представляют собой непрерывное пространство в памяти). Как только вы меняете один элемент в кортеже, создается совершенно новый кортеж. Это делает их отличными для хранения и доступа к нескольким элементам, а также соответствия шаблонов на них, но вы определенно не хотите содержать много элементов.