Sé que consdevuelve una secuencia y conjdevuelve una colección. También sé que conj"agrega" el artículo al final óptimo de la colección, y conssiempre "agrega" el artículo al frente. Este ejemplo ilustra ambos puntos:
¿Hay ejemplos de listas en las que conjvs. consexhiben comportamientos diferentes, o son realmente intercambiables? Expresado de manera diferente, ¿hay algún ejemplo en el que una lista y una secuencia no se puedan usar de manera equivalente?
Tenga en cuenta que estos no son realmente intercambiables; en particular, clojure.lang.Consno implementa clojure.lang.Counted, por lo que un countsobre que ya no es una operación de tiempo constante (en este caso probablemente reduciría a 1 + 3 - 1 al proviene de recorrido lineal en el primer elemento, el 3 viene de (next (cons 4 '(1 2 3))ser PersistentListy así Counted).
La intención detrás de los nombres es, creo, que conssignifica construir una seq. 1 , mientras que conjsignifica conjugar un elemento en una colección. El seqser construido por conscomienza con el elemento pasado como primer argumento y tiene como su next/ restparte lo resultante de la aplicación de seqal segundo argumento; como se muestra arriba, todo es de clase clojure.lang.Cons. Por el contrario, conjsiempre devuelve una colección de aproximadamente el mismo tipo que la colección que se le pasó. (Aproximadamente, porque a PersistentArrayMapse convertirá en a PersistentHashMaptan pronto como supere las 9 entradas).
1 Tradicionalmente, en el mundo Lisp, conscontras (construye un par), por lo que Clojure se aparta de la tradición Lisp al hacer que su consfunción construya un seq que no tiene un tradicional cdr. El uso generalizado de conspara significar "construir un registro de un tipo u otro para mantener juntos un número de valores" es actualmente omnipresente en el estudio de los lenguajes de programación y su implementación; eso es lo que se quiere decir cuando se menciona "evitar la consulta".
¡Qué artículo tan fantástico! No sabía que había un tipo de Contras. ¡Bien hecho!
Daniel Yankowsky
Gracias. Feliz de escuchar que. :-)
Michał Marczyk
2
Por cierto, como caso especial, (cons foo nil)devuelve un singleton PersistentList(y lo mismo para conj).
Michał Marczyk
1
Otra magnífica explicación. ¡Realmente eres un jedi clojure!
dbyrne
1
En mi experiencia, tratar las listas como listas y no como seqs es importante cuando el rendimiento importa.
cgrand
11
Tengo entendido que lo que dice es cierto: conj en una lista es equivalente a contras en una lista.
Puede pensar en conj como una operación de "insertar en algún lugar" y en contras como una operación de "insertar en la cabeza". En una lista, es más lógico insertar al principio, por lo que conj y cons son equivalentes en este caso.
Otra diferencia es que debido a que conjtoma una secuencia como primer argumento, funciona bien altercuando se actualiza refa alguna secuencia:
(dosync(alter a-sequence-ref conj an-item))
Esto básicamente lo hace (conj a-sequence-ref an-item)de manera segura para subprocesos. Esto no funcionaría con cons. Consulte el capítulo sobre Concurrencia en la programación de Clojure de Stu Halloway para obtener más información.
(cons foo nil)
devuelve un singletonPersistentList
(y lo mismo paraconj
).Tengo entendido que lo que dice es cierto: conj en una lista es equivalente a contras en una lista.
Puede pensar en conj como una operación de "insertar en algún lugar" y en contras como una operación de "insertar en la cabeza". En una lista, es más lógico insertar al principio, por lo que conj y cons son equivalentes en este caso.
fuente
Otra diferencia es que debido a que
conj
toma una secuencia como primer argumento, funciona bienalter
cuando se actualizaref
a alguna secuencia:Esto básicamente lo hace
(conj a-sequence-ref an-item)
de manera segura para subprocesos. Esto no funcionaría concons
. Consulte el capítulo sobre Concurrencia en la programación de Clojure de Stu Halloway para obtener más información.fuente
¿Otra diferencia es el comportamiento de la lista?
fuente
Hay funciones dedicadas en la biblioteca de Tupelo para agregar agregar o anteponer valores a cualquier colección secuencial:
fuente