Одно отличие состоит в том, что conj
принимает любое количество аргументов для вставки в коллекцию, а cons
принимает только один:
(conj '(1 2 3) 4 5 6)
; => (6 5 4 1 2 3)
(cons 4 5 6 '(1 2 3))
; => IllegalArgumentException due to wrong arity
Еще одно отличие заключается в классе возвращаемого значения:
(class (conj '(1 2 3) 4))
; => clojure.lang.PersistentList
(class (cons 4 '(1 2 3))
; => clojure.lang.Cons
Обратите внимание, что они на самом деле не взаимозаменяемы; в частности, clojure.lang.Cons
не реализует clojure.lang.Counted
, поэтому a count
on больше не является операцией с постоянным временем (в этом случае он, вероятно, уменьшится до 1 + 3 - 1 происходит от линейного обхода по первому элементу, 3 происходит от (next (cons 4 '(1 2 3))
того, чтобы быть a PersistentList
и таким образом Counted
).
Я полагаю, что cons
за этими именами стоит намерение cons (построить последовательность) 1 , тогда как conj
означает объединить элемент в коллекцию. seq
Строится путем cons
начинается с элементом , переданным в качестве первого аргумента , и имеют в качестве своегоnext
/ rest
части вещи , в результате применения seq
ко второму аргументу; как показано выше, все это классно clojure.lang.Cons
. Напротив, conj
всегда возвращает коллекцию примерно того же типа, что и переданная ей коллекция. (Примерно потому, что a PersistentArrayMap
будет преобразовано в a, PersistentHashMap
как только оно превысит 9 записей.)
1 Традиционно в мире Лиспа cons
cons (исправляет пару), поэтому Clojure отходит от традиции Лиспа в том, что его cons
функция создает последовательность, не имеющую традиционного cdr
. Обобщенное использование слова cons
«создать запись того или иного типа для хранения нескольких значений вместе» в настоящее время повсеместно используется при изучении языков программирования и их реализации; это то, что имеется в виду, когда упоминается «избегание совершения».
(cons foo nil)
возвращает синглтонPersistentList
(и аналогично дляconj
).Насколько я понимаю, то, что вы говорите, правда: cons в списке эквивалентно cons в списке.
Вы можете думать о конъюнктуре как об операции "вставить куда-нибудь", а о минусе как о операции "вставки в начало". В списке логичнее всего вставлять в начале, поэтому в этом случае "минусы" и "минусы" эквивалентны.
источник
Другое отличие состоит в том, что, поскольку
conj
в качестве первого аргумента используется последовательность, она хорошо работаетalter
при обновлении aref
до некоторой последовательности:Это в основном делает
(conj a-sequence-ref an-item)
потокобезопасным способом. Это не сработает сcons
. См. Главу «Параллелизм в программировании Clojure » Стю Хэллоуэя для получения дополнительной информации.источник
Еще одно отличие - это поведение списка?
источник
В библиотеке Tupelo есть специальные функции для добавления или добавления значений к любой последовательной коллекции:
источник