Why can't you use RSeq?

user=> (rseq [:a :b]) (:b :a) user=> (rseq (rseq [:a :b])) ClassCastException clojure.lang.APersistentVector$RSeq cannot be cast to clojure.lang.Reversible clojure.core/rseq (core.clj:1532) 

Why rseq n't rseq accept the result of a previous rseq call?

I read in docstring that the argument must be (in fact, "maybe") a vector or sort-map, and the above shows that it cannot be rseq , so I already know that. I want to know: are there any good reasons for this restriction? Is it just oversight, or is this limitation giving some important benefits?

Also, is there a convenient way to do this, other than to never call rseq ? It is hard to understand when you return rseq from one function whether some other function in another place can call rseq on it.

I ask because it is disappointing when my code throws exceptions for such an amazing reason s . If I knew why this made sense, I would be less likely to make this and similar errors.

+8
clojure reverse sequence rationale
source share
2 answers

You cannot call rseq in seq, because you need an input collection with constant temporary random access to the full-featured fullfill rseq with constant time, and seqs provide efficient head-down access (iteration).

The rseq call on the rseq result cannot be deliberately trimmed to return the original collection, since the original collection is never seq. And if calling rseq on RSeq returns something (seq coll) , it will not simplify the support (rseq (drop x (rseq coll))) . These are probably the complications that prevented language developers from supporting "recursive" rseq in general.

If you need a general reversal function, use reverse - which will be slower. If you can, you probably just want to keep a link to (seq coll) and (rseq coll) if you need both.

+4
source share

Because rseq only works for special reversible sequences. But the result of its application is the usual sequence. You can always check if you can rseq execute a sequence with a reversible? predicate reversible? :

 (defn reverse* [s] (if (reversible? s) (rseq s) (reverse s))) 

Why is this reserve not in the rseq (or reverse ) function? The reason is that rseq should guarantee runtime predictability, I think.

If you really need to cancel the assembly later, it is better to save it as a vector, for example: (rseq (vec (rseq [1 2 3])))

+3
source share

All Articles