Ein Unterschied besteht darin, dass conj
eine beliebige Anzahl von Argumenten zum Einfügen in eine Sammlung akzeptiert wird, während cons
nur eines benötigt wird:
(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
Ein weiterer Unterschied besteht in der Klasse des Rückgabewerts:
(class (conj '(1 2 3) 4))
; => clojure.lang.PersistentList
(class (cons 4 '(1 2 3))
; => clojure.lang.Cons
Beachten Sie, dass diese nicht wirklich austauschbar sind. Insbesondere clojure.lang.Cons
nicht implementiert clojure.lang.Counted
, so dass ein Ein count
es nicht länger eine konstante Zeitoperation ist (in diesem Fall würde es wahrscheinlich auf 1 + 3 reduzieren - die 1 kommt von der linearen Durchquerung über das erste Element, die 3 kommt von (next (cons 4 '(1 2 3))
einem PersistentList
und also Counted
).
Die Absicht hinter den Namen ist, glaube ich, das cons
heißt, eine Sequenz 1 zu konsultieren (zu konstruieren) , wohingegen conj
bedeutet, einen Gegenstand auf eine Sammlung zu setzen. Die seq
durch konstruiert cons
beginnt mit dem Element als erstes Argument übergeben und hat als ihre next
/ rest
Teil resultierenden das Ding von der Anwendung seq
zu dem zweiten Argument; Wie oben gezeigt, ist das Ganze von Klasse clojure.lang.Cons
. Gibt dagegen conj
immer eine Sammlung vom ungefähr gleichen Typ zurück wie die an sie übergebene Sammlung. (Ungefähr, weil aus a ein PersistentArrayMap
wird, PersistentHashMap
sobald es über 9 Einträge hinaus wächst.)
1 Traditionell gibt es in der Lisp-Welt cons
Nachteile (ein Paar), so dass Clojure von der Lisp-Tradition abweicht, indem seine cons
Funktion eine Sequenz konstruiert, die keine Tradition hat cdr
. Die verallgemeinerte Verwendung von cons
"Konstruieren eines Datensatzes irgendeiner Art, um eine Reihe von Werten zusammenzuhalten" ist derzeit beim Studium der Programmiersprachen und ihrer Implementierung allgegenwärtig. Das ist es, was gemeint ist, wenn "Vermeiden von Konsing" erwähnt wird.