在学习javascript和python的过程中,我们通常会接触到map、filter、reduce之类的一等公民高阶函数。理解map和filter是相对简单的事情,但理解reduce的话还是需要一番推敲。正值十一假期,今天这篇文章就好好讲讲reduce这个东西
我们首先以python为例,看一段reduce程序的操作:
1 | from functools import reduce |
这段程序里的操作,输入是一组整数,最后输出来的是这组整数的统计数据,比如总和sum、积product、最大最小值等等。实现这个统计操作,就可以用reduce。在functools库中,我们可以看到reduce的定义:
1 | _initial_missing = object() |
这段代码简单易懂,我们可以看到reduce函数需要一个初始值initial,并定义一个会变化的当前值value,然后会在遍历我们定义的sequence序列的过程中,不断用function(叫成reducer更加贴切)依据当前遍历到的元素element来更新当前值value(的内部状态),并在最后返回最终的value。
所以很显然,reduce这个函数,针对一个特定的sequence,返回值应当反映这个sequence的某样(些)属性。这便是reduce的意义所在了。
学过javascript的同学,会经常在网上资料看到reduce的翻译叫做归并,个人认为归并这个词已经翻译的非常贴切了,一时间也找不到更好的信达雅的表达。当然如果我们去检索英文百科,甚至还可以了解到更多的信息。
reduce是函数式编程的一个代表。我们检索函数式编程的维基百科,里面可以跳到reduce的百科,我们发现其实会跳到另一个单词的百科),叫做fold
从fold以及衍生词汇reduce、accumulate、aggregation可以看到,这类操作其实用中文翻译除了叫归并以外,叫累积、聚合也不过分(嗯这里又可以看到我们的老朋友mongodb,aggregation跟accumulate关键词都上架了),都是代表着一种遍历所有元素值,不断合并计算,得出最终结果的运算操作。fold反过来叫做unfold,对应的也是另一个单词的百科,叫做Anamorphism。Anamorphism本意是岩石变性、渐变,但在计算机领域,作为和fold相反的运算方式,是一个会不断根据当前值来生成下一个值,从而展开出来一个sequence的生成器generator(所以这种运算通俗的说,就翻译为展开即可,跟unfold也很搭)。我们熟悉的斐波那契数列,就可以用unfold/Anamorphism代表的运算方式生成。初始值为(0,1),根据(0,1)生成下一个数字1,根据(1,1)生成下一个数字2。这样不断展开下去,我们就可以得到特定长度的斐波那契数列了。