Clojure 克罗朱尔。为什么需要包装器惰性seq?
为什么需要包装器?有两个函数具有相同的结果Clojure 克罗朱尔。为什么需要包装器惰性seq?,clojure,Clojure,为什么需要包装器?有两个函数具有相同的结果 (defn seq1 [s] (lazy-seq (when-let [x (seq s)] (cons (first x) (seq1 (rest x)))))) (defn seq2 [s] (when-let [x (seq s)] (cons (first x) (seq2 (rest x))))) 这两种情况下,我得到了相同的结果没有分块序列 repl.core=> (first (ma
(defn seq1 [s]
(lazy-seq
(when-let [x (seq s)]
(cons (first x) (seq1 (rest x))))))
(defn seq2 [s]
(when-let [x (seq s)]
(cons (first x) (seq2 (rest x)))))
这两种情况下,我得到了相同的结果没有分块序列
repl.core=> (first (map println (seq1 (range 1000))))
0
nil
repl.core=> (first (map println (seq2 (range 1000))))
0
nil
repl.core=> (chunked-seq? (seq2 (range 1000)))
false
repl.core=> (chunked-seq? (seq1 (range 1000)))
false
第一个是懒惰。它仅根据需要评估序列的元素。然而,第二个是严格的,并立即通过整个序列。如果您在每个中添加一些
println
调用,则可以看到这一点:
(defn seq1 [s]
(lazy-seq
(when-let [x (seq s)]
(println "Seq1" (first x))
(cons (first x) (seq1 (rest x))))))
(defn seq2 [s]
(when-let [x (seq s)]
(println "Seq2" (first x))
(cons (first x) (seq2 (rest x)))))
(->> (range 10)
(seq1)
(take 5))
Seq1 0
Seq1 1
Seq1 2
Seq1 3
Seq1 4 ; Only iterated over what was asked for
=> (0 1 2 3 4)
(->> (range 10)
(seq2)
(take 5))
Seq2 0
Seq2 1
Seq2 2
Seq2 3
Seq2 4
Seq2 5
Seq2 6
Seq2 7
Seq2 8
Seq2 9 ; Iterated over everything immediately
=> (0 1 2 3 4)
因此,为了回答这个问题,lazy seq
仅在您希望序列的迭代只在需要时发生时才需要。如果您认为您可能不需要整个序列,或者序列是无限的,或者您希望使用map
或filter
对多个转换进行排序,则更喜欢惰性解决方案。如果您可能需要某个点的整个序列和/或需要快速随机访问,请使用严格的解决方案。您可以在此处阅读更多内容: