如何实现惰性“减少映射”功能?

发布于 2024-10-03 14:14:36 字数 1261 浏览 5 评论 0原文

我正在尝试实现“缩小地图”功能。也就是说,它应该返回一个序列,其中包含将 f 应用于 coll 的前 2 项的结果,后跟应用 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]]

实际上,它可能也应该返回未修改的第一项,以更好地模仿 < code>map,但我可以稍后解决这个问题。)

对了,现在,这就是它返回的内容:

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

How do I "push" at the end of a(ny) seq?

If我将 reduce-map 替换为 recur,这就是它返回的内容:

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

What is the Difference Between recur and true recursion in my code上面?

并且,是否有内置的,或者更好的,或更惯用的方式来实现reduce-map

最后,我想要输出序列要惰性。我是否只需将整个事情包装在lazy-seq中?

I am trying to implement a "reducing map" function. That is, it should return a sequence consisting of the result of applying f to the first 2 items of coll, followed by the result of applying f to that result and the third item in 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)))))

For example, calling this function like this:

(reduce-map sum-vector c)

should return:

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

(Actually, it should probably return the first item unmodified as well, to better mimic map, but I can fix that later.)

Right, now, this is what it returns:

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

How do I "push" at the end of a(ny) seq?

If I substitute reduce-map for recur, this is what it returns:

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

What is the difference between recur and true recursion in my code above?

And, is there a built-in, or better, or more idiomatic, way of implementing reduce-map?

Finally, I'd like the output sequence to be lazy. Do I just wrap the whole thing in lazy-seq?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

往事风中埋 2024-10-10 14:14:36

这听起来有点像 reductions

至于在 seq 末尾“推”:一般来说 seq 没有​​“结束”,参见。 (迭代 inc 0)

至于在列表末尾“推送”:列表不是为此而设计的。使用向量。使用 [] 为累加器设定种子,而不是 nil

至于lazy-seq:使用“true”递归而不是recur。这里有一个例子:

(defn integer-seq
  [start]
  (lazy-seq
    (cons start (integer-seq (inc start)))))

This sounds a little bit like reductions.

As to "pushing" at the end of seq: in general seqs don't have an "end", cf. (iterate inc 0).

As to "pushing" at the end of a list: lists are not designed for that. Use a vector. Seed your accumulator with [], not nil.

As to lazy-seq: Use "true" recursion instead of recur. Here an example:

(defn integer-seq
  [start]
  (lazy-seq
    (cons start (integer-seq (inc start)))))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文