В чем разница между clojure реализациями APersistentMap - программирование

В чем разница между clojure реализациями APersistentMap

Я пытаюсь выяснить, какая разница между PersistentHashMap, PersistentArrayMap, PersistentTreeMap и PersistentStructMap.

Также, если я использую {:a 1}, он дает мне PersistentArrayMap, но может ли это изменить любой из других, если я даю ему объекты или вещи, отличные от ключей?

4b9b3361

Ответ 1

Четыре реализованных вами списка относятся к трем группам:

  • "literal": PersistentArrayMap и PersistentHashMap: основные типы карт, используемые при работе с символами карты (хотя функции конструктора также доступны с различным поведением по обработке дубликатов ключей - в Clojure 1.5.x литералы бросают исключения, когда обнаруживают повторяющиеся ключи, функции конструктора работают как повторяющиеся слева направо conj ing, это поведение эволюционирует от версии к версии). Карты массивов получают распространение на хэш-карты при росте за пределами определенного количества записей (9 IIRC). Карты массивов существуют, потому что они быстрее для небольших карт; они также отличаются от хэш-карт тем, что они сохраняют записи в порядке ввода до продвижения на хэш-карту (вы можете использовать clojure.core/array-map для получения сколь угодно больших массивов карт, что может быть полезно, если вы действительно знаете, что вам выгодно использовать порядок вставки traversals и map не будут слишком большими, возможно, немного превышать обычный порог, NB. Последующая assoc к такой карте негабаритных массивов вернет хэш-карту). Массивные карты используют массивы с ключами и значениями чередуются; PHM использует постоянную версию массива хешей Phil Bagwell, сопоставленную с раздельной цепочкой для хэш-коллизий и отдельных типов node для преимущественно пустых и наименее полунаполненных узлов и легко представляет собой самую сложную структуру данных в Clojure.

  • sorted: PersistentTreeMap экземпляры создаются только специальным запросом (вызов sorted-map или sorted-map-by). Они реализованы как красно-черные деревья и сохраняют записи в определенном порядке, как указано компаратором compare по умолчанию, если он создан с помощью sorted-map или поставляемого пользователем компаратора, если он создан с помощью sorted-map-by.

  • специальный, возможно, устаревший: PersistentStructMap не используется очень часто и в основном рассматривается как устаревший в пользу записей, хотя я фактически не могу вспомнить прямо сейчас, если когда-либо было официальное уведомление об отказе. Первоначальная цель заключалась в том, чтобы обеспечить карты с особенно быстрым доступом к некоторым часто используемым клавишам. Теперь это можно сделать с помощью записей при использовании ключевых слов для доступа к полю (с ключевым словом в позиции оператора: (:foo instance-of-some-record-with-field-foo)), хотя важно отметить, что записи не являются = регулярными картами с одинаковыми записями.

Все эти четыре встроенных типа карты попадают в один и тот же "раздел равенства", то есть любые две карты одного из четырех классов, упомянутых выше, будут равны, если (и только если) они содержат одни и те же ключи (как определяется Clojure =) с теми же соответствующими значениями. Записи, как упоминалось выше в 3, являются похожими на карты, но каждый тип записи формирует свой собственный раздел равенства.

Ответ 2

Они представляют собой различную реализацию Persistent Map (все они расширяются APersistentMap). Таким образом, PersistentArrayMap использует массив как базовую структуру данных для реализации постоянной карты, а аналогичные другие реализации используют различные основные структуры данных.

Причина различной реализации заключается в том, что они предоставляют разные преимущества в разных ситуациях (поскольку эффективность реализации зависит от базовой структуры данных).

С точки зрения разработчика, он абстрагируется и, следовательно, вы не должны напрямую использовать их и вместо этого работать с APersistentMap абстрактным классом или интерфейсом IPersistentMap (в случае, если для определенного случая требуется некоторая проверка типа и т.д.).

В зависимости от количества элементов на карте используются различные реализации.

(type (into {} (map #(-> [% %]) (range 5))))
=> PersistentArrayMap
(type (into {} (map #(-> [% %]) (range 10))))
=> PersistentHashMap