n! = n * (n – 1) * (n – 2) * …
n!! = n * (n – 2) * (n – 4) * …
n!!! = n * (n – 3) * (n – 6) * …
要求编写3个函数,分别完成上述3种计算。
使用一般的方式写很容易实现,我们这里直接使用lambda表达式来实现:
#include <iostream>
#include <functional>
std::function<int(int)> getFactorialFunc(int n) {
return [n](int x) {
int fact = 1;
for (; x >= 1; x -= n) fact *= x;
return fact;
};
}
int main() {
// 构造要求的三个函数
autofactorial1 = getFactorialFunc(1);
autofactorial2 = getFactorialFunc(2);
autofactorial3 = getFactorialFunc(3);
// 调用
std::cout << factorial1(10) << std::endl;
std::cout << factorial2(10) << std::endl;
std::cout << factorial3(10) << std::endl;
}
编译的时候要注意,lambda表达式是C++11开始支持的,所以需要指定一下C++的版本。
g++ factorial_lambda.cpp -o factorial_lambda.out --std=c++11
运行之后的结果为:
./factorial_lambda.out
3628800
3840
280
这里作为返回值的lambda表达式,可以访问先前传入的参数,这也就是闭包。具体的语法,我们后面会讲到。
3、柯里化(Currying)。这部分小喵也是第一次接触,维基百科有如下解释:
在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。 [3]
下面给出一个例子(也是实现之前的阶乘):
#include <iostream>
#include <functional>
// 两个参数的阶乘
int factorial(int n, int step) {
int r = 1;
for (; n >= 1; n -= step) {
r *= n;
}
return r;
}
// curring化的阶乘
std::function<int(int)> currying_factorial(int step) {
return [step](int n) {
return factorial(n, step);
};
}
int main() {
// 调用普通函数
std::cout << factorial(10, 1) << std::endl;
std::cout << factorial(10, 2) << std::endl;
std::cout << factorial(10, 3) << std::endl;
// 调用currying函数
std::cout << currying_factorial(1)(10) << std::endl;
std::cout << currying_factorial(2)(10) << std::endl;
std::cout << currying_factorial(3)(10) << std::endl;
return 0;
}
4、lambda表达式整体可以被当做函数的参数或者返回值。
闭包和currying的例子就是将整个lambda表达式作为返回值。现在再举一个作为参数的例子:
#include <iostream>
#include <functional>
int operate(int x, int y, const std::function<int(int, int)> &op) {
return op(x, y);
}
int main() {
autoadd = [](int x, int y) { return x + y;};
automul = [](int x, int y) { return x - y;};
std::cout << operate(10, 5, add) << std::endl;
std::cout << operate(10, 5, mul) << std::endl;
return 0;
}










