почему clojure conj действует по-разному между вектором и картой

#vector #clojure

#вектор #clojure

Вопрос:

 > (conj [0] 1 2 3)
[0 1 2 3]
> (conj {:a "ei"} {:b "bi"})
{:b "bi", :a "ei"}
>  
 

Смотрите, когда он воздействует на вектор, он помещает 1,2,3 в его конец.
В то время как он помещает: b «bi» перед: парой map k-v
Почему это так?
Спасибо

Ответ №1:

Как и во многих реализациях хешированных карт, хешированные карты Clojure не сортируют свои записи, не сохраняют порядок, в котором они были вставлены. Это позволяет повысить производительность.

Обратите внимание, что conj также не имеет общей семантики упорядочения (он имеет семантику упорядочения для некоторых конкретных типов, таких как векторы).

Комментарии:

1. Conj имеет семантику для каждого конкретного типа. Другими словами, это полиморфная функция.

2. sorted-map — это карта clojure, которая сортирует свои записи по ключу.

3. Также обратите внимание, что этот полиморфизм не возникает из ниоткуда: это не цель упорядочивания хэш-карты. Его цель — получить доступ из значения, имеющего другое значение, т.е. Для выполнения операций «объединения». Порядок so не имеет значения. кроме того, существуют векторы или отсортированные карты

4. @Mars вот почему я специально написал «хешированные карты», а не карты (просто повторно используя терминологию на clojure.org ).

Ответ №2:

Вам не нужно заходить так далеко, как карты, чтобы получить непоследовательное поведение от conj :

 (conj [1] 2) ; [1 2]    
(conj (list 1) 2) ; (2 1)
 

Хэш-карты не имеют определенного порядка. Но для любой карты,

  • количество seq записей всегда будет одинаковым
  • vals и keys будут в согласованном порядке.

Таким образом, для карты m ,

 (= (keys m) (map key m))
(= (vals m) (map val m))
(= m (zipmap (keys m) (vals m)))
 

В настоящее время эта последовательность, по-видимому, не зависит от порядка вставки. Я проверил это на наборах, случайным образом перетасовывая случайные целые числа.