我怎样才能创建一个lazy-seq向量

sno*_*ape 5 clojure lazy-sequences

运行此按预期工作:

(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}))
Run Code Online (Sandbox Code Playgroud)

但是我想用矢量做同样的事情:

(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))
Run Code Online (Sandbox Code Playgroud)

这给了我一个堆栈溢出.为什么?

mik*_*era 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}])
Run Code Online (Sandbox Code Playgroud)

或者作为替代方案,您可以使用for本身就是懒惰的:

(defn long-seq-vec [n]
  (for [x (iterate inc n)]
    (vector x {:somekey (* x 2)})))
Run Code Online (Sandbox Code Playgroud)

我更喜欢这个,因为它避免了lazy-seq/ cons样板,避免了递归,并且在表达你的函数所做的事情时更加清晰......如果你喜欢的话,它会更加"声明".您也可以map以类似的方式使用.