如何用C ++进行精简?
时间:2020-03-06 14:54:36 来源:igfitidea点击:
什么是咖喱?
如何用C ++进行精简?
请解释STL容器中的粘合剂吗?
解决方案
简而言之,currying取一个函数f(x,y)并给定一个固定的Y,给出一个新函数g(x),其中
g(x) == f(x, Y)
在仅提供一个参数的情况下,可以调用此新函数,并将该调用传递给带有固定Y参数的原始f函数。
STL中的活页夹允许我们对C ++函数执行此操作。例如:
#include <functional>
#include <iostream>
#include <vector>
using namespace std;
// declare a binary function object
class adder: public binary_function<int, int, int> {
public:
int operator()(int x, int y) const
{
return x + y;
}
};
int main()
{
// initialise some sample data
vector<int> a, b;
a.push_back(1);
a.push_back(2);
a.push_back(3);
// here we declare a function object f and try it out
adder f;
cout << "f(2, 3) = " << f(2, 3) << endl;
// transform() expects a function with one argument, so we use
// bind2nd to make a new function based on f, that takes one
// argument and adds 5 to it
transform(a.begin(), a.end(), back_inserter(b), bind2nd(f, 5));
// output b to see what we got
cout << "b = [" << endl;
for (vector<int>::iterator i = b.begin(); i != b.end(); ++i) {
cout << " " << *i << endl;
}
cout << "]" << endl;
return 0;
}
咖喱化是一种减少将多个参数转换为嵌套函数的函数的嵌套方法,每个嵌套函数分别具有一个参数:
full = (lambda a, b, c: (a + b + c)) print full (1, 2, 3) # print 6 # Curried style curried = (lambda a: (lambda b: (lambda c: (a + b + c)))) print curried (1)(2)(3) # print 6
Currying很好,因为我们可以定义一些函数,这些函数只是使用预定义的值将其他函数包装起来,然后传递简化的函数。 C ++ STL绑定器在C ++中提供了此实现。
看一下Boost.Bind,它使Greg所示的过程更加通用:
transform(a.begin(), a.end(), back_inserter(b), bind(f, _1, 5));
这会将5绑定到f的第二个参数。
值得注意的是,这并非易事(而是部分应用)。但是,在C ++中,以常规方式使用currying很难(实际上,直到最近才有可能实现),并且经常使用部分应用程序。
使用tr1简化Gregg的示例:
#include <functional>
using namespace std;
using namespace std::tr1;
using namespace std::tr1::placeholders;
int f(int, int);
..
int main(){
function<int(int)> g = bind(f, _1, 5); // g(x) == f(x, 5)
function<int(int)> h = bind(f, 2, _1); // h(x) == f(2, x)
function<int(int,int)> j = bind(g, _2); // j(x,y) == g(y)
}
Tr1功能组件使我们可以用C ++编写功能丰富的代码。同样,C ++ 0x将允许内联lambda函数也可以做到这一点:
int f(int, int);
..
int main(){
auto g = [](int x){ return f(x,5); }; // g(x) == f(x, 5)
auto h = [](int x){ return f(2,x); }; // h(x) == f(2, x)
auto j = [](int x, int y){ return g(y); }; // j(x,y) == g(y)
}
尽管C ++没有提供某些面向功能的编程语言所执行的丰富的副作用分析,但const分析和C ++ 0x lambda语法可以:
struct foo{
int x;
int operator()(int y) const {
x = 42; // error! const function can't modify members
}
};
..
int main(){
int x;
auto f = [](int y){ x = 42; }; // error! lambdas don't capture by default.
}
希望能有所帮助。

