认识什么是高阶函数?

314 阅读4分钟

什么是高阶函数?

高阶函数是一个以一个函数为参数或返回一个函数的函数。这种类型的函数在许多编程语言中都有实现,包括Go、JavaScript、Python等;而且它们有成为面试中的一个问题的趋势。很多时候,我和开发人员谈起这个概念,他们对这个名字并不熟悉,尽管他们每天都在不知不觉地使用它,所以我决定用一篇文章来介绍这个话题,让我们都清楚它们是什么以及它们如何发挥作用。

由于这个话题在多种编程语言中广泛使用,我将提供JavaScript和Python的代码样本。


一些简单的例子

让我们来看看高阶函数的一些简单例子,以进入这个话题并与代码打交道,然后我们将推进到构建一些我们使用的流行函数,这些函数是高阶函数的例子。

以一个函数作为参数

首先让我们建立一个非常简单的函数,名为doOperation ,它需要3个参数。

  • 函数操作
  • 数字1
  • 数字2

此外,我们将创建一个名为sumBothNumbers 的操作,它将简单地返回两个数字的总和。

Python。

def doOperation(operation, number1, number2):
    return operation(number1, number2)

def sumBothNumbers(number1, number2):
    return number1 + number2

doOperation(sumBothNumbers, 3, 5)

------------
Output
------------
8

JavaScript。

function doOperation(operation, number1, number2) {
    return operation(number1, number2)
}

function sumBothNumbers(number1, number2) {
    return number1 + number2
}

doOperation(sumBothNumbers, 3, 5)

------------
Output
------------
8

虽然在这种特殊情况下,有doOperation 函数似乎是多余的,甚至是错误的,但在有些情况下它是有用的,doOperation 函数可以是一个库的一部分,例如,我们可以用我们自己的操作来扩展。

返回一个函数

接下来,我们将建立一个高阶函数,它将返回一个函数。我们的函数将被称为multiplyBy ,它将接受一个数字作为参数,并返回一个将其输入乘以该数字的函数。

Python。

def multiplyBy(multiplier):
    def result(num):
        return num * multiplier
    return result

multiplyByThree = multiplyBy(3)
multiplyByThree(4)

------------
Output
------------
12

JavaScript。

function multiplyBy(multiplier) {
    return function result(num) {
        return num * multiplier
    }
}

multiplyByThree = multiplyBy(3)
multiplyByThree(4)

------------
Output
------------
12

构建filter()、map()和reduce()。

让我们使用高阶函数(它们实际上是)建立一个简单版本的流行函数。

filter() aka filtering()

filtering 函数将有2个参数,一个array 和一个test 函数,它将返回一个新的数组,其中包含所有通过测试的元素。

Python。

def filtering(arr, test):
    passed = []
    for element in arr:
        if (test(element)):
            passed.append(element)
    return passed

def isSuperNumber(num):
    return num >= 10

filtering([1, 5, 11, 3, 22], isSuperNumber)

------------
Output
------------
[11, 22]

JavaScript。

function filtering(arr, test) {
    const passed = []
    for (let element of arr) {
        if (test(element)) {
            passed.push(element)
        }
    }
    return passed
}

function isSuperNumber(num) {
    return num >= 10
}

filtering([1, 5, 11, 3, 22], isSuperNumber)

------------
Output
------------
> (2) [11, 22]

可以看出,我们的filter() 函数非常容易编码,用于例如从一个数组😛中获取所有的超级数字。

map() 又名mapping()

函数mapping 将接受2个参数:一个array 和一个transform 函数,它将返回一个新的转换数组,其中每一项都是在原数组的每个元素上调用transform 函数的结果。

Python。

def mapping(arr, transform):
    mapped = []
    for element in arr:
        mapped.append(transform(element))
    return mapped

def addTwo(num):
    return num+2

mapping([1, 2, 3], addTwo)

------------
Output
------------
[3, 4, 5]

JavaScript。

function mapping(arr, transform) {
    const mapped = []
    for (let element of arr) {
        mapped.push(transform(element))
    }
    return mapped
}

function addTwo(num) {
    return num + 2
}

mapping([1, 2, 3], addTwo)

------------
Output
------------
> (3) [3, 4, 5]

reduce() aka reducing()

函数reducing 将接受3个参数:一个reducer 函数,一个用于累加器的initial value ,以及一个array 。对于数组中的每一项,都会调用reduction函数,将累加器和当前数组元素传给它。返回值被分配给累加器。当它完成对列表中所有项的还原后,返回累积值。

Python。

def reducing(reducer, initial, arr):
    acc = initial
    for element in arr:
        acc = reducer(acc, element)
    return acc

def accum(acc, curr):
    return acc + curr

reducing(accum, 0, [1, 2, 3])

------------
Output
------------
6

JavaScript。

function reducing(reducer, initial, arr) {
    let acc = initial
    for (element of arr) {
        acc = reducer(acc, element)
    }
    return acc
}

function accum(acc, curr) {
    return acc + curr
}

reducing(accum, 0, [1, 2, 3])

------------
Output
------------
6

结语

下次当你到了那个面试的时候,或者干脆你看到一个模式,一个函数要么被返回,要么被当作参数,你就知道我们在处理高阶函数。

今天我第一次介绍了一篇涵盖一种以上语言的文章,如果你觉得这是一个展示和比较它们的好方法,或者你认为这是一个糟糕的想法,请在评论中或通过twitter告诉我,我很想听到你的想法。