Одно отличие состоит в том, что 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 counton больше не является операцией с постоянным временем (в этом случае он, вероятно, уменьшится до 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 Традиционно в мире Лиспа conscons (исправляет пару), поэтому Clojure отходит от традиции Лиспа в том, что его consфункция создает последовательность, не имеющую традиционного cdr. Обобщенное использование слова cons«создать запись того или иного типа для хранения нескольких значений вместе» в настоящее время повсеместно используется при изучении языков программирования и их реализации; это то, что имеется в виду, когда упоминается «избегание совершения».