On Jun 3, 2009, at 12:53 PM, CuppoJava wrote:

Is there a function that will return true iff calling seq on it's
argument will not throw an error? I thought it was seq?, but (seq? [1
2 3]) returns false.

Such a function might be called "seqable?". As far as I know it doesn't exist currently. I've wanted it in the past as well.

The "seq" function is implemented in Java as RT.seq:

  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);
  }

which calls RT.seqFrom:

  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 String)
          return StringSeq.create((String) 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.getSimpleName());
      }
  }

From that we could derive isSeqable in Java as

  static public bool isSeqable(Object coll){
      return
        (coll instanceof ISeq) ||
        (coll instanceof Seqable) ||
        (coll == null) ||
        (coll instanceof Iterable) ||
        (coll.getClass().isArray()) ||
        (coll instanceof String) ||
        (coll instanceof Map);
  }

(ASeq and LazySeq both implement ISeq so their two tests can be collapsed into one.)

I've checked in a Clojure version to clojure.contrib.core:

  user=> (doc seqable?)
  -------------------------
  clojure.contrib.core/seqable?
  ([x])
    Returns true if (seq x) will succeed, false otherwise.
  nil
  user=>

The one critique I have of this is that one might expect (seqable? x) to return true only if (instance? clojure.lang.Seqable x) returns true. I think the name seqable? is ideal otherwise though, so I used it.

--Steve

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to