第四章:以旧函数创建新函数

注意:此文介绍很多C++11新特性的知识(bind绑定器),这不会在此读书笔记中记录,可以在我的其它地方找到相关的笔记,或者你可以自行去学习,毕竟,C++11 是现在 C++ 学习者必备的语法。

偏函数的应用

这种通过把已知函数的一个或多个参数设定为特定值的方法创建新函数的概念称为偏函数应用。偏的意思是在计算函数结果时,只需传递部分参数,而不需要传递所有参数。

函数 std::bind1st 和 std::bind2nd 在 C++17中已经删除,C++11也不推荐使用,因为它们可以被更加通用的 std::bind 取代。std::bind 不再局限于二元函数,而是可用于任意数目参数的函数。也不限制用户指定绑定哪些参数,可以以任意顺序绑定任意数目的参数,而留下不需绑定的参数。

还有提及的地方是 如何把 bind 绑定的函数 转化成用 Lambda 表示,示意图如下:

bind转lambda.png

柯里化

柯里化的基本思想是将一个接受多个参数的函数转换为一系列只接受单个参数的函数的过程。换句话说,柯里化将一个多元函数(接受多个参数的函数)转换为一个嵌套的一元函数(每个只接受一个参数的函数)。

1
2
3
4
f(x, y, z)  # 原函数

# 柯里化后的函数
f(x)(y)(z)

在这个过程中,f(x) 返回一个新的函数,这个新函数接受参数 y,并返回另一个新的函数,这个函数接受参数 z 并返回最终结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <functional>

auto add = [](int a) {
return [a](int b) {
return [a, b](int c) {
return a + b + c;
};
};
};

int main() {
std::cout << add(1)(2)(3) << std::endl; // 输出 6
return 0;
}

偏函数与柯里化

正如读者看到的,虽然十分类似,但柯里化和偏函数应用各有优缺点,而且都有自己适用的场合。当有一个要绑定其参数的特定函数时,偏函数比较有用。在这种情况下,知道函数有几个参数,可以确切地选择哪些参数要绑定到特定的值。当函数可以有任意多个参数时,柯里化对这种通用情况十分有用。在这种情况下,std::bind 就没有用武之地了,因为既然不知道函数有几个参数,也就不知道有几个参数需要绑定到占位符,甚至不知道需要多少个占位符。

函数组合

作者通过一个单词统计列表的故事讲函数的组合,因为即每个函数自有其功能,并且该函数返回处理的结果,这些结果继续传递到下一个函数,直到完成自己的需求。

单词统计.png

函数提升

在第一章接触了提升的概念,这里展开一下。一般来说,提升是种编程模式,它提供了一种方式,把给定的函数转换成一个类似可广泛应用的函数。例如,如果有一个操作字符串的函数,提升允许程序员容易地创建一个新的函数,该函数可以操作字符串向量、列表、字符串指针、整数-字符串 map 和其他包含字符串的结构。

操作字符串集合的函数.png

读者可以创建一个高阶函数,接收操作单个字符串的任意函数,并创建一个操作字符串指针的函数。前面已经分别创建了操作字符串向量和map的函数。这些函数称为提升函数,因为它们把操作某一类型的函数提升为操作包含这种类型的结构或集合的函数。

提升函数.png


⭐️内容取自译者程继洪、孙玉梅、娄山佑《函数式编程》,仅从中取出个人以为需要纪录的内容。不追求内容的完整性,却也不会丢失所记内容的逻辑性。如果需要了解细致,建议读原书。