2010-10-25 10 views
13

Quindi c'è la lista ?, seq ?, vettore ?, mappa? e così via per determinare quale tipo di raccolta è l'argomento.Clojure: scoprire se una collezione è seq-able

Che cosa è un buon modo di dire la differenza tra

  • una mappa (cioè qualcosa che contiene coppie chiave-valore)
  • una collezione (cioè qualcosa che contiene valori)
  • un valore non raccolta come una corda.

c'è un modo migliore di

#(or (seq? %) (list? %) etc) 

risposta

9

usando seq? è quanto di più conciso e pulito, come si arriva.

clojure.contrib.core definisce:

 
seqable? 
    function 
    Usage: (seqable? x) 
    Returns true if (seq x) will succeed, false otherwise. 

http://clojure.github.com/clojure-contrib/core-api.html

fa quello avete proposto con una grande or dichiarazione di

  • già un ss
  • un'istanza di clojure.lang.Seqable
  • nil
  • istanza Iterable
  • un array
  • una stringa
  • istanza java.util.Map
+0

@kotarak grazie per aver corretto il collegamento :) –

+0

Credo che questo si sia spostato ... qualsiasi aggiornamento su dove si trova? – jayunit100

+0

Nella versione corrente di Clojure (1.5) seqable? attualmente vive in clojure.core.incubator (repo @ https://github.com/clojure/core.incubator) –

4

La funzione seq momento fa solo:

(. clojure.lang.RT (seq coll)) 

In RT.java nell'ultima versione di Clojure, troverai:

static public ISeq seq(Object coll){ 
    if(coll instanceof ASeq) 
     return (ASeq) coll; 
    else if(coll instanceof LazySeq) 
     return ((LazySeq) coll).seq(); 
    else 
     return seqFrom(coll); 
} 

static ISeq seqFrom(Object coll){ 
    if(coll instanceof Seqable) 
     return ((Seqable) coll).seq(); 
    else if(coll == null) 
     return null; 
    else if(coll instanceof Iterable) 
     return IteratorSeq.create(((Iterable) coll).iterator()); 
    else if(coll.getClass().isArray()) 
     return ArraySeq.createFromObject(coll); 
    else if(coll instanceof CharSequence) 
     return StringSeq.create((CharSequence) coll); 
    else if(coll instanceof Map) 
     return seq(((Map) coll).entrySet()); 
    else { 
     Class c = coll.getClass(); 
     Class sc = c.getSuperclass(); 
     throw new IllegalArgumentException("Don't know how to create ISeq from: " + c.getName()); 
    } 
} 

Un ASeq o uno LazySeq è già un seq. A Seqable è qualcosa che sa come restituire un seq di se stesso.

Questo lascia cose come le classi di nucleo Java, che dovrebbero essere sequibili ma che Clojure non può modificare per aggiungere un metodo seq. Quelli sono attualmente codificati in questo elenco. Non sarei sorpreso se l'implementazione fosse cambiata un giorno, magari usando i protocolli per estendere le classi di core Java invece?

4

Non dimentichiamo circa sequential?:

user=> (sequential? []) 
true 
user=> (sequential? '()) 
true 
user=> (sequential? {:a 1}) 
false 
user=> (sequential? "asdf") 
false 
0

Tutti seqables implementano marcatore clojure.lang.Seqable:

(instance? clojure.lang.Seqable x) 

Clojure 1.9 fornisce seqable?

Problemi correlati