104 votes

Clojure : cons(seq) vs conj(list)

Je sais qu' cons renvoie un et seq conj renvoie une collection. Je sais aussi qu' conj ", ajoute" le point optimal fin de la collecte, et cons toujours ", ajoute" l'élément à l'avant. Cet exemple illustre ces deux points:

user=> (conj [1 2 3] 4) //returns a collection
[1 2 3 4]
user=> (cons 4 [1 2 3]) //returns a seq
(4 1 2 3)

Pour les vecteurs, les cartes et les jeux de ces différences de sens pour moi. Toutefois, pour les listes qu'elles semblent identiques.

user=> (conj (list 3 2 1) 4) //returns a list
(4 3 2 1)
user=> (cons 4 (list 3 2 1)) //returns a seq
(4 3 2 1)

Existe-il des exemples à l'aide de listes où conj vs cons présentent des comportements différents, ou sont-ils vraiment interchangeables? Formulé différemment, est-il un exemple où une liste et un suivants ne peuvent pas être utilisés de manière équivalente?

161voto

Michał Marczyk Points 54179

Une différence est que le conj accepte un nombre quelconque d'arguments à insérer dans une collection, tout cons prend une:

(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 est 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 qu'elles ne sont pas interchangeables; en particulier, clojure.lang.Cons ne met pas en oeuvre clojure.lang.Counted, donc un count , il n'est plus une constante de temps de l'opération (dans ce cas, il serait probablement réduire à 1 + 3 -- le 1 vient de linéaire de la traversée sur le premier élément, le 3 vient d' (next (cons 4 '(1 2 3)) être PersistentList et ainsi, Counted).

L'intention derrière le nom est, je crois, que cons moyen de cons(truct seq)1, alors que conj signifie conj(oin d'un élément sur une collection). L' seq construit par cons commence avec l'élément passé en premier argument et a next / rest de la partie de la chose résultant de l'application de l' seq pour le deuxième argument; comme affiché ci-dessus, le tout est de classe clojure.lang.Cons. En revanche, conj toujours retourne une collection d'à peu près du même type que la collection passée. (En gros, parce qu'un PersistentArrayMap sera transformée en PersistentHashMap dès qu'il pousse au-delà de 9 entrées.)


1 Traditionnellement, dans le Lisp monde, cons contre(tructs une paire), donc Clojure s'écarte de la Lisp tradition en ayant son cons de la fonction construire un seq qui n'ont pas de traditionnels cdr. L'utilisation généralisée de l' cons signifie "construire un record de quelque type ou un autre d'organiser un certain nombre de valeurs" est actuellement omniprésente dans l'étude des langages de programmation et leur mise en œuvre; c'est ce que voulait dire quand ", en évitant consing" est mentionné.

12voto

Daniel Yankowsky Points 3719

Ma compréhension est que ce que vous dites est vrai : conj sur une liste équivaut à cons sur une liste.

Vous pouvez considérer conj comme étant un « insérer quelque part » opération et les cons comme étant une opération de « insert à la tête ». Sur une liste, il est plus logique d’insérer à la tête, conj et inconvénients sont équivalents en l’espèce.

9voto

user323818 Points 71

Une autre différence est que parce qu' conj prend une séquence comme premier argument, il joue bien avec alter lors de la mise à jour d'un ref pour certains séquence:

(dosync (alter a-sequence-ref conj an-item))

De ce fait fondamentalement (conj a-sequence-ref an-item) dans un thread-safe. Ce ne serait pas travailler avec cons. Voir le chapitre sur la Simultanéité dans la Programmation Clojure par Stu Halloway pour plus d'info.

3voto

FredAKA Points 38

Une autre différence est le comportement de la liste ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X