2010-10-25 14 views
13

Entonces, ¿hay lista ?, ¿seq ?, ¿vector ?, ¿mapa? y así sucesivamente para determinar qué tipo de colección es el argumento.Clojure: averiguar si una colección es seq-able

¿Qué es una buena manera de decir la diferencia entre

  • un mapa (es decir, algo que contiene los pares clave-valor)
  • una colección (es decir, algo que contiene valores)
  • un valor distinto colección como una cuerda.

¿Existe una manera mejor que

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

Respuesta

9

utilizando seq? es lo más concisa y limpia como se pone.

clojure.contrib.core define:

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

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

hace lo que propone con un gran or declaración de

  • ya una ss
  • una instancia de clojure.lang.Seqable
  • nil
  • instancia de Iterable
  • una matriz
  • una cadena
  • instancia de java.util.Map
+0

@kotarak gracias por arreglar el enlace :) –

+0

Creo que esto se ha movido ... ¿alguna actualización sobre dónde está? – jayunit100

+0

En la versión actual de Clojure (1.5) seqable? Actualmente vive en clojure.core.incubator (repo @ https://github.com/clojure/core.incubator) –

4

La función seq ahora hace sólo esto:

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

En RT.java en la última versión de Clojure, encontrará:

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 una LazySeq ya es un ss. Un Seqable es algo que sabe cómo devolver un seq de sí mismo.

Eso deja cosas como las clases de núcleo de Java, que deberían ser posibles pero que Clojure no puede modificar para agregar un método seq. Actualmente, estos están codificados en esta lista. No me sorprendería si la implementación cambiara algún día, tal vez usando protocolos para extender las clases centrales de Java.

4

No olvidemos sobre sequential?:

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

Todos seqables implementan marcador clojure.lang.Seqable:

(instance? clojure.lang.Seqable x) 

Clojure 1.9 proporciona seqable?

Cuestiones relacionadas