我们如何在 Clojure 中同时进行左右折叠? [英] How do we do both left and right folds in Clojure?

查看:17
本文介绍了我们如何在 Clojure 中同时进行左右折叠?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Reduce 工作正常,但它更像是 fold-left.有没有其他形式的 reduce 可以让我向右折叠?

Reduce works fine but it is more like fold-left. Is there any other form of reduce that lets me fold to right ?

推荐答案

让我们看看每个可能的定义:

Let's look at a possible definition of each:

(defn foldl [f val coll]
  (if (empty? coll) val
    (foldl f (f val (first coll)) (rest coll))))

(defn foldr [f val coll]
  (if (empty? coll) val
    (f (foldr f val (rest coll)) (first coll))))

注意只有foldl在尾部,递归调用可以用recur代替.所以对于 recurfoldl 不会占用堆栈空间,而 foldr 会.这就是为什么reduce 就像foldl.现在让我们尝试一下:

Notice that only foldl is in tail position, and the recursive call can be replaced by recur. So with recur, foldl will not take up stack space, while foldr will. That's why reduce is like foldl. Now let's try them out:

(foldl + 0 [1 2 3]) ;6
(foldl - 0 [1 2 3]) ;-6
(foldl conj  [] [1 2 3]) ;[1 2 3]
(foldl conj '() [1 2 3]) ;(3 2 1)

(foldr + 0 [1 2 3]) ;6
(foldr - 0 [1 2 3]) ;-6
(foldr conj  [] [1 2 3]) ;[3 2 1]
(foldr conj '() [1 2 3]) ;(1 2 3)

你有什么理由想要正确弃牌吗?我认为 foldr 最常见的用法是将一个列表从前到后放在一起.在 Clojure 中,我们不需要它,因为我们可以使用向量代替.避免堆栈溢出的另一个选择是使用惰性序列:

Is there some reason you want to fold right? I think the most common usage of foldr is to put together a list from front to back. In Clojure we don't need that because we can just use a vector instead. Another choice to avoid stack overflow is to use a lazy sequence:

(defn make-list [coll]
  (lazy-seq
    (cons (first coll) (rest coll))))

所以,如果你想正确弃牌,一些有效的替代方法是

So, if you want to fold right, some efficient alternatives are

  1. 改用矢量.
  2. 使用惰性序列.
  3. 使用reduced来短路reduce.
  4. 如果您真的想潜入兔子洞,请使用换能器.

这篇关于我们如何在 Clojure 中同时进行左右折叠?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆