【问题标题】:How to convert lazy sequence to non-lazy in Clojure如何在 Clojure 中将惰性序列转换为非惰性序列
【发布时间】:2009-10-29 04:33:42
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我很惊讶没有人问你为什么关心doall的返回值的实际类型
  • 您可以转换为矢量:(vec (take 3 (repeatedly rand)))

标签: clojure lazy-evaluation


【解决方案1】:

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

【讨论】:

  • 我已将其更改为已接受的答案。在相关说明中,您可以通过什么方式确定 LazySeq 之前是否已被评估过?
  • 我相信你只要打电话给realized?。
  • 应该有一个realize 操作来匹配realized?。
  • 这一切都很好。但是由于像contains? 这样的一些函数并不关心你是否实现了惰性序列,所以这回答了所提出的具体问题,但对问题的标题却不太关心。
【解决方案2】:

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

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

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

【讨论】:

  • 这是最好的答案。
  • 接受的答案在技术上是正确的,但这个答案对我最有用。我试图将一个函数映射到一个向量上,然后将结果吐出到一个文件中,即使在调用 doall 之后,该文件也包含“clojure.lang.LazySeq@address”而不是序列的内容。在返回的值映射上调用 vec 得到了我需要吐出到文件中的内容。
  • @JesseRosalia 很高兴知道所有 SO 中唯一的 Rich Hickey 响应在技术上是正确的。 ;-)
  • (vec (my-lazy-seq)) 在以下情况下不太好:(vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]] 因为cheshire 选择从(json/parse-string) 生成惰性序列
  • 缓解上述情况是使用急切的(json/parse-string-strict)
【解决方案3】:

这个有钱人似乎知道他的 clojure 并且是绝对正确的。
但是我认为这个 code-sn-p,使用你的例子,可能是对这个问题的有用补充:

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

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

【讨论】:

  • 值得注意的是,您不需要强制realized? 的整个序列返回true。例如。 (let [r (range) r? (realized? r)] (doall (take 1 r)) [r? (realized? r)]) => [false true]
  • 这个有钱人 :D 哈哈
  • @nimrod :) 这个双关语本来应该是“hís clojure”。
  • 对于那些不知道的人,“有钱人”发明了 Clojure。
  • @AlexCoventry 你的例子返回[true true]
【解决方案4】:

我偶然发现了这个blog 帖子,关于doall 不是递归的。为此,我发现帖子中的第一条评论起到了作用。大致如下:

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

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

【讨论】:

    【解决方案5】:
    (.getClass (into '() (take 3 (repeatedly rand))))
    

    【讨论】:

    • 这是个糟糕的主意。它反转输入序列。
    • 当然,在这种情况下,反转输入没有区别,因为它们只是 3 个随机数...... :-)
    猜你喜欢
    • 1970-01-01
    • 2011-10-25
    • 2011-06-26
    • 2010-12-08
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    相关资源
    最近更新 更多