REQUEST: Add seqable? to core

179 views
Skip to first unread message

Sean Devlin

unread,
Jul 27, 2009, 1:49:22 PM7/27/09
to Clojure
Rich,

There have been a few times in this thread that people have tried to
determine if a function was seqable, and used the following code

(seq? a-collection)

While this code is great for determining if a-collection is a
sequence, it is sometimes not what people want. Often the following
code is meant to be used:

(instance? clojure.lang.Seqable a-collection)

I speculate that many people have something like the following code in
their library collection:

(defn seqable?
"Returns true if (seq x) should work. That is, it tests if x
implements clojure.lang.Seqable"
[x]
(instance? clojure.lang.Seqable x))

Could something like seqable? be added to core? Am I mistaken in the
need for standardizing this function?

Sean

PS - Sorry if this isn't the right avenue for feature requests.

Chris Kent

unread,
Jul 29, 2009, 3:45:11 PM7/29/09
to Clojure
I was thinking exactly the same thing. It feels like there should be
a better way than instance? ...Sequable. Unless there's a reason
that's a bad idea.

Chris

Chouser

unread,
Jul 29, 2009, 3:59:04 PM7/29/09
to clo...@googlegroups.com
On Mon, Jul 27, 2009 at 1:49 PM, Sean Devlin<francoi...@gmail.com> wrote:
>
> There have been a few times in this thread that people have tried to
> determine if a function was seqable, and used the following code
>
> (seq? a-collection)
>
> While this code is great for determining if a-collection is a
> sequence, it is sometimes not what people want.  Often the following
> code is meant to be used:
>
> (instance? clojure.lang.Seqable a-collection)

I think the only thing that currently extends Seqable is
IPersistentCollection, which is testable with 'coll?'

> (defn seqable?
>  "Returns true if (seq x) should work.  That is, it tests if x
> implements clojure.lang.Seqable"
>  [x]
>  (instance? clojure.lang.Seqable x))

Note however that seq works on things that are not
IPersistentCollections nor Seqable, like java collections,
strings, etc.

user=> (filter #(Character/isUpperCase %) "Works For Me")
(\W \F \M)

user=> (seq (java.util.HashMap. {:a 1, :b 2, :c 3}))
(#<Entry :c=3> #<Entry :b=2> #<Entry :a=1>)

> PS - Sorry if this isn't the right avenue for feature requests.

No worries -- you're going about this exactly the right way.
:-)

--Chouser

Rich Hickey

unread,
Jul 29, 2009, 4:37:34 PM7/29/09
to Clojure


On Jul 29, 3:45 pm, Chris Kent <cjk...@gmail.com> wrote:
> I was thinking exactly the same thing.  It feels like there should be
> a better way than instance? ...Sequable.  Unless there's a reason
> that's a bad idea.
>

There's some discussion here and the linked-to message:

http://groups.google.com/group/clojure/msg/385098fabfcaad9b

Rich

John Harrop

unread,
Jul 29, 2009, 11:06:36 PM7/29/09
to clo...@googlegroups.com
How about defining seqable? in terms of whether seq works, using try catch?

Or better yet:

(defmacro if-seq
  "If (seq obj) makes sense, evaluates expr1 with name bound to (seq obj); otherwise evaluates expr2."
  [[name obj] expr1 expr2]
  `(let [[~name failed#] (try
                           [(seq ~obj) false]
                           (catch Throwable _# [~expr2 true]))]
    (if failed# ~name ~expr1)))

user=> (if-seq [foo [1 2 3]] foo 0)
(1 2 3)
user=> (if-seq [foo (let [a (java.util.ArrayList.)] (.add a 17) a)] foo 0)
(17)
user=> (if-seq [foo "string"] foo 0)
(\s \t \r \i \n \g)
user=> (if-seq [foo 'bar] foo 0)
0

J. McConnell

unread,
Jul 30, 2009, 2:46:58 AM7/30/09
to clo...@googlegroups.com
On Wed, Jul 29, 2009 at 11:06 PM, John Harrop <jharr...@gmail.com> wrote:
How about defining seqable? in terms of whether seq works, using try catch?

I think this is the only DRY way to do it, but I know Rich has expressed in the past the he does not approve of using exception handling as a form of flow control.

Stephen Gilardi added a seqable? function to clojure.contrib.core here:

http://github.com/richhickey/clojure-contrib/commit/bc07de7c3b1058f4263bd7b1c424f771fb010005

Regards,

- J.
Reply all
Reply to author
Forward
0 new messages