2012-03-09 9 views
9

che vedo questo comportamento in Clojure 1.2.1:(non = (tipo `(1)) (tipo` (1 2))) ;; Perché? (Elenco unico elemento, la sintassi-citazione, Cons, PersistentList)

user=> (type '(1 2)) 
clojure.lang.PersistentList 
user=> (type `(1 2)) ;; notice syntax-quote 
clojure.lang.Cons 
user=> (type '(1)) 
clojure.lang.PersistentList 
user=> (type `(1)) 
clojure.lang.PersistentList 

mi aspettavo `(1) di essere un Contro proprio come` (1 2) è .

Ho anche provato:

user=> (type (cons 1 nil)) 
clojure.lang.PersistentList 
user=> (type (cons 1 `())) 
clojure.lang.Cons 
user=> (type (cons 1 '())) 
clojure.lang.Cons 
user=> (type (cons 1 [])) 
clojure.lang.Cons 

Allora, qual è la ragione per la `(1) e (cons 1 zero) per essere PersistentLists?

risposta

4

Come dice amalloy, non si dovrebbe programmare contro questi tipi esatti ma contro l'astrazione seq.

Tuttavia, penso di poter indovinare il motivo. I moduli Clojure che producono un PersistentList in definitiva chiamano RT.java, in particolare il metodo cons(Object x, Object coll). Inizia con un controllo piuttosto strano: if(coll == null) return new PersistentList(x), dopodiché crea un oggetto Cons se tale controllo non viene superato. Se si guarda a earlier versions of the code, è possibile trovare questo:

static public IPersistentCollection cons(Object x, IPersistentCollection y) { 
    if(y == null) 
     return new PersistentList(x); 
    return y.cons(x); 
} 

Quindi, in una versione precedente della funzione, la chiamata è stato spedito al metodo del secondo argomento cons, in modo che il caso in cui il secondo argomento era null (vale a dire nil in Clojure) necessaria una gestione speciale. Le versioni successive non eseguono questo dispacciamento (o lo fanno in realtà in modo diverso, presumibilmente per supportare una più ampia varietà di tipi di raccolta), ma il controllo è stato mantenuto poiché non infrange alcun codice scritto correttamente.

+0

Grazie per la risposta! Questo spiega il comportamento. Ho pensato che ci fosse un buon motivo per cui le cose funzionassero in questo modo, ma se capisco correttamente questo è solo un capriccio, giusto? –

+0

Penso di sì. Se vuoi davvero scoprirlo, prova a rimuoverlo e vedere se qualcosa si rompe. –

+0

Probabilmente lo farò. Grazie. –

4

Se ti interessa la differenza, il tuo programma non è corretto. Sono entrambi i seq, nel senso che (seq? x) restituisce true; il resto sono dettagli di implementazione da cui non si deve dipendere.

+1

Non ne ho bisogno per nessun programma :) Spero solo di imparare qualcosa su Clojure. –

Problemi correlati