Erlang Thursday - lists:foldl/3 and lists:foldr/3

今天Erlang Thursday讲的是 lists:foldl/3lists:foldr/3

lists:foldl/3 是Erlang版的 reduce 函数。 lists:foldl/3 接收三个入参:一个函数,一个初始的累加器,一个列表,输出一个单一的值。

foldl的第一个入参是一个接收两个参数的函数,一个是当前循环到的列表元素,另一个是积累的值。这个函数的输出值作为循环到下一个列表元素的时候的累加器,或者当循环结束的时候作为foldl函数的输出值。

foldl的第二个入参是一个累加器的初始值。与其他一些语言不同,在其他语言里这个累加器的初始值是可选的,而且常常是使用循环列表的第一个元素作为默认值,但是在Erlang里,累加器的初始值必需作为lists:foldl/3和lists:foldr/3两个函数的入参。

第三个入参,也就是最后一个入参是将被循环遍历的列表。

1
2
3
4
5
6
7
8
9
10
11
12
lists:foldl(fun(X, Sum) -> Sum + X end, 0, [1, 2, 3, 4, 5]).
% 15
lists:foldl(fun(X, Product) -> Product * X end, 1, [1, 2, 3, 4, 5]).
% 120
lists:foldl(fun(X, Accum) -> io:format("~p ", [X]) end, void, [1, 2, 3, 4, 5]).
% 1 2 3 4 5 ok
lists:foldl(fun(X, Accum) -> io:format("~p ", [X]), Accum end, void, [1, 2, 3, 4, 5]).
% 1 2 3 4 5 void
lists:foldl(fun(X, Accum) -> Accum + X end, 1, []).
% 1
lists:foldl(fun(X, Result) -> lists:umerge(Result, X) end, [], [[1, 2, 3], [3, 5, 8], [11, 13, 17]]).
% [1,2,3,5,8,11,13,17]

在Erlang的lists模块里也包含foldr/3函数,它是从左到右(译者注:应该是从右到左,可能是作者手误)遍历列表或者说是从最后一个元素到第一个元素遍历列表。

1
2
3
4
lists:foldr(fun(X, Accum) -> io:format("~p ", [X]), Accum end, void, [1, 2, 3, 4, 5]).
% 5 4 3 2 1 void
lists:foldr(fun(X, Accum) -> Accum + X end, 1, []).
% 1

Erlang文档里指出foldl/3通常比foldr/3更好,因为foldl/3是尾递归,而foldr/3不是。

原文链接: https://www.proctor-it.com/erlang-thursday-lists-foldl-3-and-lists-foldr-3/