2011-09-15 12 views
10

Clojure:¿Incoherencia con las secuencias de Clojure?

1:13 user=> (first (conj '(1 2 3) 4)) 
4 
1:14 user=> (first (conj [1 2 3] 4)) 
1 
; . . . 
1:17 user=> (first (conj (seq [1 2 3]) 4)) 
4 

que entender lo que está pasando, pero si esto llegara a trabajar de manera diferente?

+0

He estado aprendiendo Clojure desde mayo de este año. Me pareció que profundizar en ejercicios como este era muy útil, especialmente teniendo en cuenta que nunca aprendí un lenguaje parecido a Lisp antes de Clojure. – octopusgrabbus

Respuesta

20

Documentación para conj (de clojure.org):

conj [oin]. Devuelve una nueva colección con el xs 'agregado'. (elemento conj nil) devuelve (elemento). La 'adición' puede ocurrir en diferentes 'lugares' dependiendo del tipo de hormigón.

Es más eficiente "agregar" elementos al final de un vector, mientras que es más eficiente hacerlo al principio de las listas. conj usa lo que sea más eficiente para la estructura de datos que le proporcione.

En los ejemplos que das, '(1 2 3) y (seq [1 2 3]) tanto implemento ISeq (ver documentation for seq?), mientras que [1 2 3] no.

Clojure's conj finalmente llama al método cons (no debe confundirse con la función cons - este método es código interno de clojure) en la estructura de datos subyacente; para vectores (PersistentVector), cons agrega elementos al final, mientras que para las listas se agregan al frente (el método cons para PersistentList s devuelve una nueva lista con el nuevo elemento como encabezado y la lista existente como su cola) .

+0

El último párrafo que creo que es incorrecto (al menos en Clojure 1.2.1): '(contra 4 [1 2 3])', por ejemplo, no agrega el elemento sino que lo precede, lo que da como resultado '(4 1 2 3) '. El resto de la respuesta, sin embargo, es absolutamente correcto. –

+0

Tiene razón, Zach, pero la función 'contras 'de Clojure (implementada en' Clojure.lang.RT/cons') es diferente de los métodos 'contras' implementados en' PersistentVector', 'PersistentList' et cetera. – Gert

+0

Ah, ahora te entiendo. Tal como está redactado, parece que te estás refiriendo a la función central 'contra'. –

6

Si nos fijamos en Clojure Data Structures

verá que conj funciona de forma diferente con las listas y vectores.

conj coloca el elemento agregado al principio de la lista y al final de un vector.

También sugiero mirar Clojure API conj

que tiene algunos buenos ejemplos. ClojureDocs en general tiene algunos ejemplos muy buenos para la mayoría de los comandos de Clojure.

Cuestiones relacionadas