Jedna różnica polega na tym, że conjakceptuje dowolną liczbę argumentów do wstawienia do kolekcji, podczas gdy conszajmuje tylko jeden:
(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
Kolejna różnica dotyczy klasy wartości zwracanej:
(class (conj '(1 2 3) 4))
; => clojure.lang.PersistentList
(class (cons 4 '(1 2 3))
; => clojure.lang.Cons
Zauważ, że nie są one w rzeczywistości zamienne; w szczególności clojure.lang.Consnie implementuje clojure.lang.Counted, więc a counton nie jest już operacją o stałym czasie (w tym przypadku prawdopodobnie zmniejszyłaby się do 1 + 3 - 1 pochodzi z liniowego przechodzenia po pierwszym elemencie, 3 pochodzi z (next (cons 4 '(1 2 3))bycia a PersistentListi w ten sposób Counted).
Uważam, że intencją kryjącą się za nazwami jest conscons (truct a seq) 1 , podczas gdy conjoznacza połączenie (łączenie pozycji z kolekcją). seqSkonstruowany przez consrozpoczęciem z elementem przekazanym jako pierwszy argument i ma na next/ restczęści Rzecz wynikające z zastosowania seqdo drugiego argumentu; jak pokazano powyżej, całość jest klasowa clojure.lang.Cons. W przeciwieństwie do tego, conjzawsze zwraca zbiór mniej więcej tego samego typu, co przekazana do niego kolekcja. (Z grubsza, ponieważ a PersistentArrayMapzostanie zamieniony w a, PersistentHashMapgdy tylko przekroczy 9 wpisów.)
1 Tradycyjnie, w świecie Lispa, conscons (tructs a pair), więc Clojure odchodzi od tradycji Lispa polegając na tym, że jego consfunkcja konstruuje sekwencję, która nie ma tradycyjnego cdr. Uogólnione użycie conswyrażenia „skonstruuj rekord jakiegoś lub innego typu, aby przechowywać razem pewną liczbę wartości” jest obecnie wszechobecne w badaniach języków programowania i ich implementacji; to właśnie ma na myśli, gdy wspomina się o „unikaniu szkód”.