gpt4 book ai didi

Clojure 扁平化和惰性

转载 作者:行者123 更新时间:2023-12-02 22:28:34 24 4
gpt4 key购买 nike

不确定在构建惰性序列时使用展平时观察到的行为是什么。

查看 clojure.core 中的源代码,我可以看到 flatten 函数调用了 filter,因此应该返回一个惰性序列 - 我认为。然而下面的代码片段给了我一个计算器错误。在片段中,当对 flatten 的调用替换为对 concat 的调用时,它工作得很好

(defn l-f [c]
(if (nil? c) []
(lazy-seq (flatten (cons [[ :h :j] :a :B] (l-f (rest c)))))))


(take 10 (l-f (repeat 2))) is how I invoke it.

这是一个相当人为的例子。我也知道 flatten 和 concat 会给我嵌套级别不同的序列。

我试图弄清楚为什么 flatten 似乎打破了惰性,尽管我对 clojure.core 中代码的(有限)理解表明并非如此。

最佳答案

懒惰只会带你走这么远 - 懒惰只是意味着序列在创建时没有完全实现,但是从另一个惰性序列构建一个惰性序列有时需要向前看一些值。在这种情况下,flatten 的实现不能很好地适应您调用它的递归方式。

首先,flatten 函数调用tree-seq 对集合的内容进行深度优先遍历。反过来,tree-seq 使用提供的序列调用 mapcat,它委托(delegate)给 apply,后者实现序列中的前几项以确定要调用的函数的数量。实现序列中的前几项会导致对 l-f 的递归调用,后者对剩余参数调用 flatten,并陷入无限循环。

在这种特殊情况下,不需要递归调用 flatten,因为第一次调用之后的任何调用都将无效。因此,可以通过将惰性序列的生成与其展平分开来修复您的函数:

(defn l-f [c]                                                      
(letfn [(l-f-seq [x] (if-let [s (seq x)]
(lazy-seq (cons [[:h :j] :a :B] (l-f-seq (rest s))))
[]))]
(flatten (l-f-seq c))))

关于Clojure 扁平化和惰性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12626401/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com