为什么你不能 RSeq 一个 RSeq?

Why can't you RSeq an 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)

为什么 rseq 不能接受之前调用 rseq 的结果?

我在文档字符串中读到参数必须是(实际上,“可以是”)向量或排序映射,上面显示它不能是 RSeq,所以我已经知道了。我想知道的是:这种限制有充分的理由吗?这只是一个疏忽,还是这个限制提供了一些重要的好处?

此外,除了从不调用 rseq 之外,是否有方便的解决方法?很难知道,当你从一个函数 return 一个 RSeq 时,其他地方的其他函数是否会调用 rseq

我问这个问题是因为看到我的代码为 such surprising reasons 抛出异常令人沮丧。如果我知道为什么这是有道理的,我可能就不太可能犯这种错误和类似的错误。

你不能在 seq 上调用 rseq,因为你需要一个具有恒定时间随机访问的输入集合来 fullfill rseq 的恒定时间性能特征,而 seqs 只提供高效访问(迭代)从头向下。

rseq 的结果调用 rseq 不能对 return 原始集合进行特殊处理,因为原始集合从来都不是序列。如果在 RSeq 上调用 rseq 会 return 某些东西 (seq coll),那将不会直接支持 (rseq (drop x (rseq coll)))。可能正是这些复杂性导致语言实现者根本不支持 "recursive" rseq。

如果您需要一般的反转函数,请使用 reverse - 这会更慢。如果可以,您可能只想保留对 (seq coll)(rseq coll) 的引用(如果您需要两者)。

因为rseq只适用于特殊的可逆序列。但是它的应用结果是一个普通的seq。您始终可以检查是否可以 rseq 带有 reversible? 谓词的序列:

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

为什么这个回退不在 rseq(或 reverse)函数本身?原因是rseq应该保证其执行时间的可预测性,我猜。

如果以后确实需要将集合逆向返回,最好将其保存为向量例如:(rseq (vec (rseq [1 2 3])))