Une différence est qu'elle conj
accepte n'importe quel nombre d'arguments à insérer dans une collection, alors qu'elle cons
n'en prend qu'un:
(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
Une autre différence réside dans la classe de la valeur de retour:
(class (conj '(1 2 3) 4))
; => clojure.lang.PersistentList
(class (cons 4 '(1 2 3))
; => clojure.lang.Cons
Notez que ceux-ci ne sont pas vraiment interchangeables; en particulier, clojure.lang.Cons
ne met pas en œuvre clojure.lang.Counted
, donc a count
on ce n'est plus une opération à temps constant (dans ce cas il se réduirait probablement à 1 + 3 - le 1 provient d'un parcours linéaire sur le premier élément, le 3 vient d' (next (cons 4 '(1 2 3))
être a PersistentList
et ainsi Counted
).
L'intention derrière les noms est, je crois, cela cons
signifie de contre (truire une suite) 1 , alors que cela conj
signifie de conj (joindre un élément à une collection). Le seq
cours de construction par cons
commence avec l'élément passé en premier argument et a pour next
/ rest
partie la chose résultant de l'application de seq
la deuxième argument; comme affiché ci-dessus, le tout est de classe clojure.lang.Cons
. En revanche, conj
renvoie toujours une collection à peu près du même type que la collection qui lui est passée. (En gros, parce que a PersistentArrayMap
sera transformé en a PersistentHashMap
dès qu'il dépassera 9 entrées.)
1 Traditionnellement, dans le monde Lisp, cons
contre (truit une paire), Clojure s'écarte donc de la tradition Lisp en ayant sa cons
fonction construire un seq qui n'a pas de traditionnel cdr
. L'utilisation généralisée de cons
pour signifier "construire un enregistrement d'un type ou d'un autre pour contenir un certain nombre de valeurs ensemble" est actuellement omniprésente dans l'étude des langages de programmation et de leur implémentation; c'est ce que signifie «éviter de consommer».
(cons foo nil)
renvoie un singletonPersistentList
(et de même pourconj
).Je crois comprendre que ce que vous dites est vrai: conj sur une liste équivaut à contre sur une liste.
Vous pouvez considérer conj comme une opération "insérer quelque part", et par contre comme une opération "insérer en tête". Sur une liste, il est plus logique d'insérer en tête, donc conj et cons sont équivalents dans ce cas.
la source
Une autre différence est que parce que
conj
prend une séquence comme premier argument, il joue bien avecalter
lors de la mise à jourref
d'une séquence:Cela se fait essentiellement
(conj a-sequence-ref an-item)
d'une manière thread-safe. Cela ne fonctionnerait pas aveccons
. Voir le chapitre sur la concurrence dans la programmation de Clojure par Stu Halloway pour plus d'informations.la source
Une autre différence est le comportement de la liste?
la source
Il existe des fonctions dédiées dans la bibliothèque Tupelo pour ajouter ou ajouter des valeurs à n'importe quelle collection séquentielle:
la source