【问题标题】:Why can't you rseq an RSeq?为什么你不能 rseq 一个 RSeq?
【发布时间】:2016-09-22 17:09:05
【问题描述】:
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

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

【问题讨论】:

    标签: clojure sequence reverse rationale


    【解决方案1】:

    您不能在 seq 上调用 rseq,因为您需要一个具有恒定时间随机访问的输入集合来完全填充 rseq 的恒定时间性能特征,并且 seqs 仅提供从头部的有效访问(迭代)下来。

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

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

    【讨论】:

    • 谢谢!我在想RSeqrseq 返回的对象)可以很容易地在恒定时间内反转,只需打开RSeq,但我认为你已经确定了:向量不是序列。我还是 Clojure 的新手,我仍然经常将“返回序列”误读为“返回序列的东西,比如向量”,而不是“返回类似于迭代器的东西”。
    • 再想一想:难道RSeq 不能通过在原始向量或排序图上返回一个序列来在恒定时间内成为Reversible
    • 是的,它可以工作,但对于原始的 RSeq 来说很容易。例如,您不能轻易支持 (rseq (drop 1 (rseq coll))。
    • 啊,现在我明白了。您可以将其添加到您的答案中吗?
    • @BenKovitz 完成 :-)
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 那么,仅调用rseq 来制作您将在您完全了解的代码中使用的东西是一种常见的做法,或者至少是明智的做法吗?我想知道我是否应该将rseq 视为一个“危险”函数,例如“好吧,当您调用rseq 时,您实际上是在请求运行时异常。”
    • 好吧,如果您从“协议”的角度来看它(某些功能集只能应用于某些类型的集合),一切都会变得干净,例如:assocupdate只能用Associative 调用,rseq 只能用Reversible 调用等等。所以是的,你应该记住在你的代码中,并仔细检查外部库返回的值的类型。
    • 为了回答您关于常见做法的问题,在过去的六年中,我将 Clojure 作为我的日常工作,我没有看到任何调用 rseq 的电话。
    • 一旦我删除所有rseqs,也许我也会有一份梦想的工作。 :)
    猜你喜欢
    • 2017-03-09
    • 1970-01-01
    • 2015-10-18
    • 2012-11-20
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    相关资源
    最近更新 更多