如何用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. }
希望能有所帮助。