2011-09-15 10 views
10

Clojure:Incoerenza con le sequenze di 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 

capisco cosa sta succedendo, ma dovrebbe questo lavoro in modo diverso?

+0

Ho studiato Clojure da maggio di quest'anno. Ho trovato approfondimento in esercizi come questo per essere molto utile, soprattutto perché non ho mai imparato un linguaggio simile al Lisp prima di Clojure. – octopusgrabbus

risposta

20

Documentazione per conj (da clojure.org):

conj [oin]. Restituisce una nuova collezione con xs 'added'. (conj nil item) restituisce (articolo). L''aggiunta' può succedere in "luoghi" diversi a seconda del tipo di calcestruzzo.

È più efficiente "aggiungere" elementi alla fine di un vettore, mentre è più efficiente farlo all'inizio delle liste. conj utilizza quello che è il più efficiente per la struttura dati che gli viene assegnata.

Negli esempi si danno, '(1 2 3) e (seq [1 2 3]) sia attuare ISeq (vedi documentation for seq?), mentre [1 2 3] non lo fa.

Clojure conj chiama in ultimo il metodo cons (da non confondere con la funzione cons - questo metodo è il codice del clojure interno) sulla struttura dati sottostante; per i vettori (PersistentVector), cons aggiunge elementi alla fine, mentre per le liste vengono aggiunte al fronte (il metodo cons per PersistentList s restituisce una nuova lista con il nuovo elemento come la sua testa, e la lista esistente come la coda) .

+0

L'ultimo paragrafo non è corretto (almeno in Clojure 1.2.1): '(cons 4 [1 2 3])', ad esempio, non aggiunge l'elemento ma lo antepone, risultando in '(4 1 2 3) '. Il resto della risposta, però, è assolutamente corretto. –

+0

Hai ragione, Zach, ma la funzione 'cons' di Clojure (implementata in' Clojure.lang.RT/cons') è diversa dai metodi 'cons' implementati in' PersistentVector', 'PersistentList' et cetera. – Gert

+0

Ah, ora ti capisco. Il modo in cui è formulato, sembra che tu ti stia riferendo alla funzione principale 'cons'. –

6

Se si guarda alla Clojure Data Structures

vedrai che conj funziona in modo diverso con le liste e vettori.

conj mette l'elemento aggiunto alla parte anteriore della lista e alla fine di un vettore.

Ho anche suggerire a guardare Clojure API conj

che ha qualche esempio piacevoli. ClojureDocs ha in generale alcuni esempi molto carini per la maggior parte dei comandi Clojure.