8
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?很难知道,当您RSeq从一个函数返回一个函数时,其他地方的其他函数是否会调用rseq它。

我之所以这么问,是因为看到我的代码因为如此令人惊讶原因抛出异常令人沮丧。如果我知道为什么这是有道理的,我可能不太可能犯这种错误和类似的错误。

4

2 回答 2

4

您不能调用rseqseq,因为您需要一个具有恒定时间随机访问的输入集合来访问 fullfillrseq的恒定时间性能特征,并且 seq 仅提供从头向下的有效访问(迭代)。

调用rseq的结果rseq不能是特殊情况以返回原始集合,因为原始集合永远不是 seq。如果调用rseqRSeq 会返回一些东西(seq coll),那将无法直接支持(rseq (drop x (rseq coll)))。可能正是这些复杂性使语言实现者根本无法支持“递归” rseq。

如果您需要通用反转功能,请使用reverse- 会更慢。如果可以的话,你可能只想保留一个参考(seq coll)(rseq coll)如果你需要两者。

于 2016-05-25T08:50:28.263 回答
3

因为rseq仅适用于特殊的可逆序列。但其应用的结果是一个普通的seq。您可以随时检查是否可以rseq使用reversible?谓词序列:

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

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

如果您以后确实需要将集合反向,则最好将其保留为向量,例如:(rseq (vec (rseq [1 2 3])))

于 2016-05-25T09:06:15.107 回答