gpt4 book ai didi

clojure - 对 lazy-seq 的调用应该有什么范围?

转载 作者:行者123 更新时间:2023-12-01 13:18:49 26 4
gpt4 key购买 nike

我正在编写 Recamán's Sequence 的惰性实现,并且遇到了一些关于应该在哪里调用 lazy-seq 的困惑。

我今天早上想到的第一个版本是:

(defn lazy-recamans-sequence []
(let [f (fn rec [n seen last-s]
(let [back (- last-s n)
new-s (if (and (pos? back) (not (seen back)))
back
(+ last-s n))]
(lazy-seq ; Here
(cons new-s (rec (inc n) (conj seen new-s) new-s)))))]
(f 0 #{} 0)))

然后我意识到我对 lazy-seq 的放置有点随意,它可以放置得更高以包含更多的计算:

(defn lazy-recamans-sequence2 []
(let [f (fn rec [n seen last-s]
(lazy-seq ; Here
(let [back (- last-s n)
new-s (if (and (pos? back) (not (seen back)))
back
(+ last-s n))]
(cons new-s (rec (inc n) (conj seen new-s) new-s)))))]
(f 0 #{} 0)))

然后我回头看了一个review that someone gave me last night :

(defn recaman []
(letfn [(tail [previous n seen]
(let [nx (if (and (> previous n) (not (seen (- previous n))))
(- previous n)
(+ previous n))]
; Here, inside "cons"
(cons nx (lazy-seq (tail nx (inc n) (conj seen nx))))))]
(tail 0 0 #{})))

他们在 cons 的调用中有他们自己的!

想了想,好像也没什么区别。对于更广泛的范围(如第二个版本),更多代码位于传递给 LazySeq 的显式函数中。然而,范围越窄,函数本身可能越小,但由于传递的函数涉及递归调用,它无论如何都会执行相同的代码。

他们的表现似乎几乎完全相同,并给出了相同的答案。有什么理由更喜欢将 lazy-seq 放在一个地方而不是另一个地方吗?这仅仅是一种风格选择,还是会产生实际影响?

最佳答案

在前两个示例中,lazy-seq 包装了 cons 调用。这意味着当您生成调用该函数时,您会立即返回一个惰性序列,而无需计算序列的第一项。

在第一个示例中,let 表达式仍在 lazy-seq 之外,因此第一项的值会立即计算,但返回的序列仍然是惰性序列和 not realized .

第二个例子与第一个相似。 lazy-seq 包装了 cons 单元格以及 let block 。这意味着该函数将立即返回,并且仅当调用者开始使用惰性序列时才计算第一项的值。

在第三个例子中,列表中第一项的值是立即计算的,只有返回序列的尾部是惰性的。

Is there any reason to prefer placing lazy-seq in one place over another?

这取决于你想达到什么目的。你想立即返回一个序列而不计算任何值吗?在这种情况下,使 lazy-seq 的范围尽可能广泛。否则尝试将 lazy-seq 的范围限制为只计算序列的尾部。

关于clojure - 对 lazy-seq 的调用应该有什么范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51845415/

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