如何理解高阶函数
如何理解高阶函数
昨天开始读 SICP,这本书作为 MIT 所有理工科类学生的公共必修课(类似于咱们的高数),还是挺有价值的,很清楚的解释了一些基本概念,这里先总结一下高阶函数吧。
高阶函数的定义是接受一个函数作为参数,或者返回一个函数的函数。不过这样的解释作为总结也就罢了, 如果用来学习、理解的话。。。。。。还是看具体例子吧。
函数
我们知道函数是对过程的抽象,或者说是对某种过程的通用描述,比如说下面这个求绝对值的过程:
-
5 -> |5| = 5 -1 -> |-1| = 1 0 -> |0| = 0
求绝对值的过程是判断一个数是否大于等于 0,如果是的话,返回这个数,否则返回它的相反数。于是,为了对这个“复杂”过程进行抽象,我们可以定义一个函数 abs(x)
, 它专门用来计算一个数的绝对值。
可别小看这个貌似人人都会的简单的过程,它实际上是一件值得总结的事情,abs(x)
的价值绝不在于它实现求绝对值的过程,而是告诉我们:
如果有一系列操作,仅仅是输入的参数不同,但是对于参数的处理过程大致相同,我们就可以用函数来抽象这个操作。
求和
我们都熟练的掌握如何计算 1 到 n 中所有自然数的和,自然就可以定义一个函数 sum(a, b)
,表示从 a 到 b 中所有自然数的和,但如果被求和的不是自然数,而是某个表达式呢?
学过数学的人都知道,有一个符号叫求和符号,也即是这玩意:Σ,上述的 a 和 b 分别是它的上下标,后面还跟着一个函数 f(x)
:
Σf(x) = f(a) + f(a+1) + …… + f(b)
我们可以看到,Σ 也满足之前对函数的定义,首先它表示了一些列操作,随着输入参数(这时候是一个函数)的不同,它代表了不同的操作。但不管怎样,它对参数的处理方式总是类似的:依次把 a 到 b 中的每一个数代入到参数函数中,并且求和。
高阶函数
很多现代编程语言都实现了数组的 map 方法,它本质上就是一个高阶函数。为什么这么说,或者说为什么要在这里设计一个高阶函数呢?我们可以看一下 map 方法的本质:
for item in array: item = handle(item)
你可以看到这个过程的变量其实是 handle
函数,也就是说 map
方法其实是对 “不同的 handle 函数的相似使用” 这一过程的抽象,因此它的参数必须是一个函数,这也就是为什么 map 是一个高阶函数。
同理,reduce 等也是高阶函数。
总结
高阶函数就是玩函数的,它把函数当做变量来用,回顾一下函数的定义:
如果有一系列操作,仅仅是输入的参数不同,但是对于参数的处理过程大致相同,我们就可以用函数来抽象这个操作。
这里并没有规定参数是什么,如果是一个数字,那我们可以理解为这是个普通函数;如果变量自身就是一个函数,我们可以理解为这是一个高阶函数。
不过我一直坚持的理念是,概念和名词只是用来简化、抽象某个具体的描述,它应该被用来方便人们进行交流而不是约束你的思维。所以高阶函数就是函数,不用做刻意的区分。