5

运行它按预期工作:

(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))

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

4

1 回答 1

8

主要原因是向量不是惰性的——所以into调用贪婪地消耗产生的递归序列long-seq-vec并导致堆栈溢出。作为这个推论,不可能创建一个无限向量(通常,如果它是惰性或循环的,您只能创建一个无限数据结构)。

它在第一个示例中起作用,因为cons当 consing 到一个惰性序列的前面时,它很乐意表现出惰性,因此该序列可以是无限的。

假设您实际上想要一个无限的向量序列,我建议您这样做:

(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以类似的方式使用。

于 2012-08-31T00:44:22.147 回答