运行此按预期工作:
(defn long-seq [n]
(lazy-seq (cons
(list n {:somekey (* n 2)})
(long-seq (+ n 1)))))
(take 3 (long-seq 3))
; => ((3 {:somekey 6}) (4 {:somekey 8}) (5 {:somekey 10}))
但是我想用矢量做同样的事情:
(defn long-seq-vec [n]
(lazy-seq (into
(vector (list n {:somekey (* n 2)}))
(long-seq-vec (+ n 1)))))
(take 3 (long-seq-vec 3))
这给了我一个堆栈溢出。为什么?
答案 0 :(得分:8)
主要原因是向量不是懒惰的 - 因此into
调用贪婪地消耗long-seq-vec
生成的递归序列并导致堆栈溢出。作为其必然结果,不可能创建无限向量(通常,只有在惰性或循环时才能创建无限数据结构)。
它适用于第一个例子,因为cons
非常乐意在懒惰序列的前面进行懒惰行为,所以序列可以是无限的。
假设你真的想要一个无限的向量序列,我会建议像:
(defn long-seq-vec [n]
(lazy-seq (cons
(vector n {:somekey (* n 2)})
(long-seq-vec (+ n 1)))))
(take 3 (long-seq-vec 3))
=> ([3 {:somekey 6}] [4 {:somekey 8}] [5 {:somekey 10}])
或者作为替代方案,您可以使用本身就是懒惰的for
:
(defn long-seq-vec [n]
(for [x (iterate inc n)]
(vector x {:somekey (* x 2)})))
我更喜欢这个,因为它避免了lazy-seq
/ cons
样板,避免了递归,并且在表达你的函数所做的事情时更加清晰......如果你愿意的话,它会更加“声明”。您也可以以类似的方式使用map
。