计算机科学基础
高阶函数
高阶函数提供了一种更强大的方法,通过允许函数接受函数作为参数或返回值,将解决问题的方案进行泛化。其他所有函数都被称为一阶函数。在数学中,高阶函数的一个例子是导数函数,它以一个函数作为输入,并生成另一个函数(输入函数的导数)作为输出。在计算机科学中,map
函数接收一个任意函数和一个数据集(如列表),并将该函数应用于数据集中每一个数据项。另一个例子是 reduce
(或 fold
)函数,它接收一个输入函数和数据集,通过该函数对数据集中的所有项进行聚合。例如,如果输入函数是加法,reduce
函数返回数据集中所有项的和;如果输入函数是乘法,reduce
函数返回数据集中所有项的乘积。
高阶函数还允许我们动态地将现有函数组合成新的函数。例如,给定两个函数 y=f(x)y = f(x) 和 y=g(x)y = g(x),以及 b=f(a)b = f(a)、c=g(b)c = g(b),我们可以创建一个新函数 y=fg(x)=f(g(x))y = fg(x) = f(g(x)),从而 c=fg(a)c = fg(a)。
示例
map
以下脚本使用 Snap! 中内置的 map
块(函数),将同一个函数应用于列表中的每一个元素。
此内置 map
块(函数)用于将一个函数应用到列表中的每一个元素。
要应用不同的函数,我们只需找到或实现所需的函数并将其作为 map
块的第一个参数。例如,使用一个接收两个参数的乘法函数时,Snap! 足够智能,能够将列表中的每个元素作为函数的两个参数来应用。因此,结果列表将包含原始列表中每个元素的平方。
此 map
块被用于对列表中的每个元素应用乘法函数。由于传入的函数接收两个参数,当函数应用到列表中的某个元素时,相同的元素被用作两个参数。
map
块将对多个数据项应用同一函数的模式进行了泛化。尽管实现 map
块本身并不简单(查看其源代码可以看到其复杂性),但它使程序员的思考过程更简单,因为程序员无需关心列表的迭代,只需专注于需要应用的函数。
reduce
以下两个示例使用 Snap! 中的内置 reduce
函数,分别计算一个数字列表的和与积。
此块使用加法函数对列表中的每个元素求和,计算总和。
此块使用 Snap! 的内置 reduce
函数计算数字列表的乘积。
注意,reduce
(或 combine with
)函数可以接收任何具有两个输入参数的函数,用于将一个值列表聚合为单个值。通过使用高阶函数,我们可以创建可自定义的泛化解决方案,从而解决更广泛的问题。
将块作为数据返回
以下示例展示了将块用作数据的用法。此块接收两个 reporter
块作为参数,并将其用于生成一个新的 report
值(一个新块)。新块会将两个输入 reporter
块应用于未知的输入值。需要注意的是,环绕 report
值的“环”(灰色框架)非常重要。环内的内容会被视为数据,而不是程序。这意味着不会立即执行环内的函数应用,而是作为数据返回,这正是高阶函数的需求。
此块接收两个 reporter
块作为输入参数,并返回一个新块作为输出。新块的功能是两个输入块表示的函数的组合。当调用新块时,它将输入值应用于两个函数并返回结果。
要使用组合函数,我们可以调用 compose
函数,传入两个输入函数,并使用 call
块对输入值执行组合块,如以下脚本所示。
compose
块被调用以根据两个输入块创建一个组合块(函数)。然后,该组合块被应用于输入值 3。该调用的结果为 1+2+3=6。
通过这个 compose
块,我们可以在需要时通过组合现有函数动态定义新函数。这种泛化方法是高阶函数所特有的,也是其强大的原因。