Pregunta

Estoy tratando de implementar una función de "reducir mapa". Es decir, se debe devolver una secuencia que consiste en el resultado de aplicar f a los 2 primeros elementos de coll, seguido por el resultado de aplicar f a ese resultado y el tercer elemento de coll, etc.

(def c [[0 0 0 0] [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]])

(defn- sum-vector [v1 v2]
  (map + v1 v2))

(defn reduce-map [f coll & acc]
  (if (< (count coll) 2)
    (if (empty? acc) coll acc)
    (let [head (apply f (take 2 coll))
          tail (drop 2 coll)]
      (recur f (conj tail head) (conj acc head)))))

Por ejemplo, llamar a esta función como esta:

(reduce-map sum-vector c)

debería volver:

[[1 0 0 0] [1 1 0 0] [1 1 1 0] [1 1 1 1]]

(En realidad, probablemente debería devolver el primer elemento no modificado, así, a map imitar mejor, yo la puedo arreglar esto más adelante.)

Bien, ahora, esto es lo que devuelve:

((1 1 1 1) (1 1 1 0) (1 1 0 0) (1 0 0 0))

¿Cómo hacer yo "empuje" al final de un ss (ny)?

Si reduce-map sustituto de recur, esto es lo que devuelve:

(((1 1 1 1) ((1 1 1 0) ((1 1 0 0) ((1 0 0 0))))))

¿Cuál es la diferencia entre recur y verdadero recursividad en mi código de seguridad?

Y, ¿Hay un built-in, o mejor, o más idiomática, forma de implementar reduce-map?

Por último, me gustaría que la secuencia de salida a la pereza. No acabo de envolver todo el asunto en lazy-seq?

¿Fue útil?

Solución

Esto suena un poco como reductions .

En cuanto a "empujar" al final de la SEC: en SEQs generales no tienen un "fin", cf. (iterate inc 0).

En cuanto a "empujar" al final de una lista: las listas no están diseñados para eso. Utilizar un vector. Las semillas de su acumulador con [], no nil.

En cuanto a lazy-seq: Uso recursividad "verdadero" en lugar de recur. Aquí un ejemplo:

(defn integer-seq
  [start]
  (lazy-seq
    (cons start (integer-seq (inc start)))))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top