我在Clojure中尝试了以下代码,期望返回非惰性序列的类:
(.getClass (doall (take 3 (repeatedly rand))))
然而,这仍然返回 clojure.lang.LazySeq
。我的猜测是 doall
确实会评估整个序列,但由于原始序列对于备忘仍然有用,因此它返回原始序列。
那么,从惰性序列创建非惰性序列的惯用方法是什么?
我在Clojure中尝试了以下代码,期望返回非惰性序列的类:
(.getClass (doall (take 3 (repeatedly rand))))
然而,这仍然返回 clojure.lang.LazySeq
。我的猜测是 doall
确实会评估整个序列,但由于原始序列对于备忘仍然有用,因此它返回原始序列。
那么,从惰性序列创建非惰性序列的惯用方法是什么?
doall
是你需要的全部。仅仅因为序列具有LazySeq类型并不意味着它具有待定的评估。懒惰序列会缓存其结果,因此您只需走一遍懒惰序列(就像doall
一样)即可强制执行所有内容,从而使其非懒惰。 seq
不会强制求值整个集合。
realized?
。 - toofarsidewaysrealize
操作来匹配realized?
。 - Reut Sharabanicontains?
)无论您是否实现了惰性序列都不会受到影响,因此这回答了特定问题的提问,但对问题的标题则不太相关。 - matanster这在某种程度上是一个分类问题。懒惰序列只是序列的一种类型,就像列表、向量或映射表一样。因此答案当然是:"取决于你想要获取哪种非懒惰序列:
可以从以下选项中选择:
(doall ...)
(apply list (my-lazy-seq)) 或 (into () ...)
(vec (my-lazy-seq))
你可以按照需求选择最适合你的序列类型。
(vec (my-lazy-seq))
is not so nice in situations like the following:
(vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]]
Since cheshire
chooses to produce a lazy-seq from (json/parse-string)
- codeasone(json/parse-string-strict)
。 - codeasone=> (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]
- Alex Coventry[true true]
。 - user4813927我偶然发现了这篇关于doall
不是递归的博客文章(链接)。对此,我在文章的第一条评论中找到了解决方法,大致如下:
(use 'clojure.walk)
(postwalk identity nested-lazy-thing)
我在一个单元测试中发现这很有用,其中我想强制评估一些 map
的嵌套应用程序以强制出现错误条件。
(.getClass (into '() (take 3 (repeatedly rand))))
doall
返回值的实际类型。 - tar(vec (take 3 (repeatedly rand)))
。 - Kris