If you only need to iterate over the input data, and this is actually some kind of container, you usually do not need to perform any special conversions. Two special cases that come to mind are handled by enumeration-seq and iterator-seq .
I believe that there is really no ready-made function in the kernel to determine if an object is a valid input for seq . The corresponding code is in the clojure.lang.RT seq and seqFrom and basically tries to use several features in turn; I find it seqable? tested the same possibilities - you could do the same. Existing functions like coll? , seq? sequential? , cannot catch at least some of them (especially arrays and strings); coll? probably closest sequential? flatten is especially used (therefore, it is limited in its ability to actually smooth things).
Of course, there is always the opportunity to try applying seq and catch the exception (not what I would recommend):
(defn seq-at-all-costs [x] (try (seq x) (catch IllegalArgumentException e (list x)))) ; NB. '(x) wouldn't work, since it would ; cause a literal symbol x to be returned, ; as noted in my comment on the question
You can also do something similar to speed things up (I hope I would definitely set myself the task):
(defprotocol IKnowHowToSeqYou (seq-knowledgeably [this])) (defn seq! [x] (try (seq-knowledgeably x) (catch IllegalArgumentException e (try (seq x) (extend-type (class x) IKnowHowToSeqYou (seq-knowledgeably [this] (seq this))) (catch IllegalArgumentException e (extend-type (class x) IKnowHowToSeqYou (seq-knowledgeably [this] (list this))))) (seq-knowledgeably x))))
I have to say, however, that I almost never - perhaps never - feel the need for seqable? . The reason is probably because it is relatively unusual that I do not know at all what types of objects I will deal with at any time, and in those rare cases, as a rule, I look through cases / apply protocols / use ellipses, etc. d.
Here is the checklist used by RT.seq and RT.seqFrom at the moment:
if the input is already seq (which for RT.seq means " clojure.lang.ASeq instance", not ISeq ), it is returned unchanged;
if he is a lazy seq, he is forced and the result is returned;
otherwise, if it implements Seqable , then he asked to create seq of its contents;
if it is nil ( null ), nil returned;
if Iterable , the iterator seq is returned;
if it is an array, an array of seq is returned;
if it is CharSequence , the string seq is returned;
if it is java.util.Map , seq is returned over its recordset;
otherwise an exception is thrown.
source share