101

我在 Clojure 中尝试了以下操作,期望返回非惰性序列的类:

(.getClass (doall (take 3 (repeatedly rand))))

但是,这仍然返回clojure.lang.LazySeq。我的猜测是,它doall确实评估了整个序列,但返回了原始序列,因为它仍然对记忆有用。

那么从惰性序列创建非惰性序列的惯用方法是什么?

4

5 回答 5

170

doall是你所需要的全部。仅仅因为seqhas 类型LazySeq并不意味着它有待评估。Lazyseq会缓存它们的结果,因此您需要做的就是将lazy 遍历seq一次(就像doall这样做一样)以强制执行所有操作,从而使其成为非懒惰的。seq强制评估整个集合。

于 2009-10-29T10:41:28.220 回答
79

这在某种程度上是分类学的问题。惰性序列只是列表、向量或映射的一种序列。所以答案当然是“这取决于你想要得到什么类型的非惰性序列:
你可以选择:

  • 一个前惰性(完全评估)惰性序列 (doall ... )
  • 顺序访问的列表 (apply list (my-lazy-seq)) OR (into () ...)
  • 用于以后随机访问的向量(vec (my-lazy-seq))
  • 如果你有一些特殊的目的,一张地图或一组。

您可以拥有最适合您需要的任何类型的序列。

于 2009-10-29T17:10:29.467 回答
22

这个有钱的家伙似乎知道他的clojure,而且是绝对正确的。
但我认为这个代码片段,使用你的例子,可能是对这个问题的有用补充:

=> (realized? (take 3 (repeatedly rand))) 
false
=> (realized? (doall (take 3 (repeatedly rand)))) 
true

确实类型没有改变,但实现

于 2013-09-06T09:07:24.837 回答
7

我偶然发现了这篇关于不递归的博客文章。doall为此,我发现帖子中的第一条评论起到了作用。类似于以下内容:

(use 'clojure.walk)
(postwalk identity nested-lazy-thing)

我发现这在单元测试中很有用,我想强制评估一些嵌套应用程序map以强制出现错误条件。

于 2015-08-29T20:32:32.080 回答
5
(.getClass (into '() (take 3 (repeatedly rand))))
于 2009-10-29T16:03:18.887 回答