Fold
(又名reduce
)被认为是一个非常重要的高阶函数。Map
可以用fold
(see here)来表示。但对我来说,这听起来更多的是学术而不是实践。典型的用法可能是获取数字的和、积或最大值,但这些函数通常接受任意数量的参数。既然(+ 2 3 5)
运行得很好,为什么还要写(fold + 0 '(2 3 5))
呢?我的问题是,在什么情况下使用fold
最简单或最自然
发布于 2011-03-16 21:28:07
fold
的要点是它更抽象。这并不是说你可以做以前做不到的事情,而是你可以更容易地完成它们。
使用fold
,您可以将定义在两个元素上的任何函数泛化为应用于任意数量的元素。这是一个胜利,因为它通常更容易编写,测试,维护和修改一个应用两个参数的单个函数,而不是一个列表。而且,用一个简单的函数来编写、测试、维护等总是比使用两个功能相似但并不完全相同的函数更容易。
由于fold
(以及map
、filter
和friends)具有定义良好的行为,因此使用这些函数通常比显式递归更容易理解代码。
基本上,一旦你有了一个版本,你就可以“免费”得到另一个版本。最终,您只需做更少的工作即可获得相同的结果。
发布于 2011-03-16 21:27:21
这里有几个简单的例子,reduce
确实工作得很好。
求出每个子列表的最大值之和
Clojure:
user=> (def x '((1 2 3) (4 5) (0 9 1)))
#'user/x
user=> (reduce #(+ %1 (apply max %2)) 0 x)
17
球拍:
> (define x '((1 2 3) (4 5) (0 9 1)))
> (foldl (lambda (a b) (+ b (apply max a))) 0 x)
17
从列表构造地图
Clojure:
user=> (def y '(("dog" "bark") ("cat" "meow") ("pig" "oink")))
#'user/y
user=> (def z (reduce #(assoc %1 (first %2) (second %2)) {} y))
#'user/z
user=> (z "pig")
"oink"
有关reduce
的更复杂的clojure示例,请查看my solution to Project Euler problems 18 & 67。
另请参阅:reduce vs. apply
发布于 2011-03-18 09:18:26
在Common Lisp中,函数不接受任何数量的参数。
在每个Common Lisp实现CALL-ARGUMENTS-LIMIT中都定义了一个常量,该常量必须大于或等于50。
这意味着任何这样的可移植编写的函数都应该接受至少50个参数。但也有可能只有50。
存在此限制是为了允许编译器可能使用优化的调用方案,而不提供一般情况,在这种情况下可以传递无限数量的参数。
因此,要在可移植的Common Lisp代码中真正处理大型(大于50个元素)列表或向量,有必要使用迭代构造、reduce、map等。因此,也有必要不使用(apply '+ large-list)
,而使用(reduce '+ large-list)
。
https://stackoverflow.com/questions/5331746
复制相似问题