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

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

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

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

有帮助吗?

解决方案

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

其他提示

这在某种程度上是一个分类问题。 惰性序列只是序列的一种类型 就像列表、矢量或地图一样。所以答案当然是“这取决于您想要获得什么类型的非惰性序列:
从以下选项中选择:

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

您可以选择最适合您需求的任何类型的序列。

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

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

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

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

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

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

(.getClass (into '() (take 3 (repeatedly rand))))
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top