如何在Clojure中将惰性序列转换为非惰性序列

时间:2009-10-29 04:33:42

标签: clojure lazy-evaluation

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

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

但是,这仍然会返回clojure.lang.LazySeq。我的猜测是doall会对整个序列进行评估,但会返回原始序列,因为它仍然可用于记忆。

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

5 个答案:

答案 0 :(得分:149)

doall 就是您所需要的。仅仅因为seq具有类型LazySeq并不意味着它具有待定的评估。懒惰的seqs缓存它们的结果,所以你需要做的就是走懒惰的seq一次(就像doall一样)以强制它全部,从而使它变得非懒惰。 seq 强制要对整个集合进行评估。

答案 1 :(得分:63)

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

  • 一个ex-lazy(完全评估)的懒惰序列 (doall ... )
  • 顺序访问的列表 (apply list (my-lazy-seq)) OR (into () ...)
  • 用于以后随机访问的向量(vec (my-lazy-seq))
  • 如果您有特殊目的,请使用地图或集合。

您可以根据自己的需要选择任何类型的序列。

答案 2 :(得分:21)

这个富家似乎知道他的咒语,绝对是对的 但是我认为这个代码片段,使用你的例子,可能是这个问题的有用补充:

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

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

答案 3 :(得分:7)

我偶然发现了blog这篇关于doall没有递归的帖子。为此,我发现帖子中的第一条评论就是诀窍。有点像:

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

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

答案 4 :(得分:5)

(.getClass (into '() (take 3 (repeatedly rand))))
相关问题