Question

Je suis en train de mettre en œuvre une fonction « réduction de la carte ». Autrement dit, il doit renvoyer une séquence constituée du résultat de l'application f pour les 2 premiers éléments de coll, suivi par le résultat de l'application f à ce résultat et le troisième élément dans 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)))))

Par exemple, appeler cette fonction comme ceci:

(reduce-map sum-vector c)

devrait revenir:

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

(En fait, il devrait revenir probablement le premier élément non modifié et, pour mieux schématiser map, mais je peux corriger plus tard.)

Bon, maintenant, voici ce qu'elle retourne:

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

Comment puis-je "pousser" à la fin d'un (ny) suivants?

Si je reduce-map de remplacement pour recur, voici ce qu'elle retourne:

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

Quelle est la différence entre recur et vrai récursion dans mon code ci-dessus?

est-il intégré, ou mieux, ou plus idiomatiques, le mode de mise en œuvre reduce-map?

Enfin, je voudrais la séquence de sortie pour être paresseux. Est-ce que je viens envelopper le tout dans lazy-seq?

Était-ce utile?

La solution

Cela sonne un peu comme reductions .

Quant à « pousser » à la fin de suivants: en seqs généraux ne sont pas une « fin », cf. (iterate inc 0).

Quant à « pousser » à la fin d'une liste: les listes ne sont pas conçus pour cela. Utilisez un vecteur. Semences votre accumulateur avec [], non nil.

Quant à lazy-seq: Utilisez récursion "true" au lieu de recur. Voici un exemple:

(defn integer-seq
  [start]
  (lazy-seq
    (cons start (integer-seq (inc start)))))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top