Wie implementiere ich eine lazy „reduzieren Karte“ -Funktion?
Frage
Ich versuche, eine „Verringerung der Karte“ -Funktion zu implementieren. Das heißt, es sollte eine Sequenz zurück, bestehend aus dem Ergebnis der f
zu den ersten 2 Artikel von coll
Anwendung, gefolgt von dem Ergebnis der f
zu diesem Ergebnis und dem dritten Element in coll
Anwendung, 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)))))
Zum Beispiel, Aufruf dieser Funktion wie folgt aus:
(reduce-map sum-vector c)
zurückkehren sollte:
[[1 0 0 0] [1 1 0 0] [1 1 1 0] [1 1 1 1]]
(Eigentlich sollte es wahrscheinlich kehrt das erste Element als auch unverändert, besser zu imitieren map
, aber ich kann das in Ordnung bringen später.)
So, jetzt, das ist, was es gibt:
((1 1 1 1) (1 1 1 0) (1 1 0 0) (1 0 0 0))
Wie kann ich "Push" am Ende eines (ny) f?
Wenn ich Ersatz reduce-map
für recur
, das ist, was es gibt:
(((1 1 1 1) ((1 1 1 0) ((1 1 0 0) ((1 0 0 0))))))
Was ist der Unterschied zwischen recur
und wahrer Rekursion in meinem obigen Code?
Und gibt es eine eingebaute, oder besser, oder mehr idiomatisch, Art und Weise der Umsetzung reduce-map
?
Schließlich möchte ich die Ausgangssequenz, faul sein. Muss ich wickeln nur die ganze Sache in lazy-seq
?
Lösung
Das klingt ein wenig wie reductions
.
Was am Ende des seq „Schieben“: im Allgemeinen ASTA kein „Ende“ hat, vgl (iterate inc 0)
.
In Bezug auf „Schieben“ am Ende einer Liste: Listen werden für das nicht ausgelegt ist. Verwenden Sie einen Vektor. Seed Ihren Akku mit []
, nicht nil
.
In Bezug auf lazy-seq
: Verwenden Sie "true" Rekursion statt recur
. Hier ein Beispiel:
(defn integer-seq
[start]
(lazy-seq
(cons start (integer-seq (inc start)))))