2012-08-30 15 views
5

La ejecución de este funciona como se espera:¿Cómo puedo crear un vector perezoso-ss

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

Sin embargo, me gustaría hacer lo mismo con un vector:

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

Esto me da una pila rebosar. ¿Por qué?

Respuesta

8

La razón principal es que vectores no son perezosos - lo que la llamada into consume con avidez las secuencias recursivas producidos por long-seq-vec y resulta en un desbordamiento de pila. Como corolario de esto, no es posible crear un vector infinito (en general, solo puedes crear una estructura de datos infinita si es floja o cíclica).

Funciona en el primer ejemplo porque cons es bastante feliz de comportarse perezosamente cuando se pasa al frente de una secuencia perezosa, por lo que la secuencia puede ser infinita.

Suponiendo que realmente desea una secuencia infinita de vectores me gustaría sugerir algo como:

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

O como alternativa, se puede utilizar for que es perezoso en sí mismo:

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

I prefiera esto ya que evita el texto repetitivo lazy-seq/cons, evita la repetición y es un poco más claro al expresar lo que hace su función ... es un poco más "declarativo" si lo desea. También puede usar map de una manera similar.

Cuestiones relacionadas