怠zyな「マップを減らす」機能を実装するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/4254763

質問

「マップの削減」関数を実装しようとしています。つまり、適用の結果からなるシーケンスを返す必要があります f の最初の2つのアイテムへ coll, 、適用の結果が続きます f その結果と3番目のアイテムに 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))

(NY)seqの最後に「プッシュ」するにはどうすればよいですか?

代用する場合 reduce-map にとって recur, 、これが返すものです:

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

違いは何ですか recur そして、上記の私のコードの真の再帰?

と、 組み込み、またはより良い、またはより慣用的な実装方法はありますか reduce-map?

最後に、出力シーケンスを怠zyにしたいと思います。すべてを包みますか? lazy-seq?

役に立ちましたか?

解決

これは少し似ています reductions.

配列の終わりに「プッシュ」について:一般的には「終了」はありません。 (iterate inc 0).

リストの最後に「プッシュ」することについて:リストはそのために設計されていません。ベクトルを使用します。アキュムレータをシードします [], 、 いいえ nil.

について lazy-seq: :ではなく「True」再帰を使用します recur. 。ここに例:

(defn integer-seq
  [start]
  (lazy-seq
    (cons start (integer-seq (inc start)))))
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top