Как реализовать ленивую функцию уменьшения карты?

Я пытаюсь реализовать функцию «уменьшения карты». То есть он должен возвращать последовательность, состоящую из результата применения f к первым двум элементам coll, за которым следует результат применения f к этому результату и третий элемент в coll и т. д.

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

Например, вызывая эту функцию следующим образом:

(reduce-map sum-vector c)

должен вернуться:

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

(На самом деле, он, вероятно, также должен возвращать первый элемент без изменений, чтобы лучше имитировать map, но я могу исправить это позже.)

Вот что он возвращает:

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

Как "вставить" в конец последовательности?

Если я заменю reduce-map на recur, это то, что он возвращает:

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

В чем разница между recur и истинной рекурсией в приведенном выше коде?

И есть ли встроенный, или лучший, или более идиоматический способ реализации reduce-map?

Наконец, я бы хотел, чтобы выходная последовательность была ленивой. Мне просто завернуть все это в lazy-seq?


person Pedro Silva    schedule 23.11.2010    source источник


Ответы (1)


Это немного похоже на reductions.

Что касается «нажатия» в конце последовательности: обычно последовательности не имеют «конца», ср. (iterate inc 0).

Что касается "проталкивания" в конец списка: списки для этого не предназначены. Используйте вектор. Заполните свой аккумулятор [], а не nil.

Что касается lazy-seq: используйте «истинную» рекурсию вместо recur. Вот пример:

(defn integer-seq
  [start]
  (lazy-seq
    (cons start (integer-seq (inc start)))))
person kotarak    schedule 23.11.2010
comment
Что ж, это было быстро. Спасибо! - person Pedro Silva; 23.11.2010