这是一个补充性答案,有助于解释地图和折痕。对于下面的示例,我将使用此列表。请记住,此列表是不可变的,因此它将永远不会改变:
var numbers = [1, 2, 3, 4, 5]
我将在示例中使用数字,因为它们会导致易于阅读的代码。但是请记住,折叠可用于传统命令式循环可用于的任何事情。
一个地图需要的东西的清单,和一个函数,并返回使用该功能修改的列表。每一项都传递给函数,并成为函数返回的值。
最简单的例子就是在列表中的每个数字上添加一个数字。我将使用伪代码使其与语言无关:
function add-two(n):
return n + 2
var numbers2 =
map(add-two, numbers)
如果打印了numbers2
,您将看到[3, 4, 5, 6, 7]
哪个是第一个列表,每个列表中添加了2个元素。注意,该功能add-two
已被允许map
使用。
折叠与相似,只是您需要赋予它们的函数必须带有2个参数。第一个参数通常是累加器(最常见的是左折)。累加器是循环时传递的数据。第二个参数是列表的当前项目。就像上面的map
功能一样。
function add-together(n1, n2):
return n1 + n2
var sum =
fold(add-together, 0, numbers)
如果打印,sum
您将看到数字列表的总和:15。
这是要fold
执行的参数:
这就是我们提供的功能。折叠将把当前累加器和列表的当前项目传递给函数。函数返回的结果将成为新的累加器,下一次将传递给该函数。这是在循环FP样式时“记住”值的方式。我给了它一个接受2个数字并将其相加的函数。
这是初始累加器;在处理列表中的任何项目之前,累加器的启动方式。在对数字求和时,将数字相加之前的总和是多少?0,我将其作为第二个参数传递。
最后,与地图一样,我们也将数字列表传递给地图进行处理。
如果仍然没有折痕,请考虑这一点。当你写:
# Notice I passed the plus operator directly this time,
# instead of wrapping it in another function.
fold(+, 0, numbers)
您基本上是将传递的函数放在列表中的每个项目之间,并将初始累加器添加到左侧或右侧(取决于它是左折还是右折),因此:
[1, 2, 3, 4, 5]
成为:
0 + 1 + 2 + 3 + 4 + 5
^ Note the initial accumulator being added onto the left (for a left fold).
等于15
map
当您想将一个列表变成相同长度的另一个列表时,请使用a 。
fold
当您要将列表变成单个值时,请使用a ,例如将数字列表求和。
正如@Jorg在评论中指出的那样,“单个值”不必像数字一样简单。它可以是任何单个对象,包括列表或元组!我其实是有褶皱点击我的方法是定义地图来讲折叠。注意累加器是如何列出的:
function map(f, list):
fold(
function(xs, x): # xs is the list that has been processed so far
xs.add( f(x) ) # Add returns the list instead of mutating it
, [] # Before any of the list has been processed, we have an empty list
, list)
老实说,一旦您理解了每种循环,您就会意识到几乎所有循环都可以用折叠或地图代替。