C 11:lambda,currying

我有以下代码.你能解释一下它是如何工作的吗?
template<typename Function,typename... Arguments>
auto curry(Function func,Arguments... args) {
    return [=](auto... rest) {
        return func(args...,rest...);
    };
}

int main() {
    auto add = [](auto x,auto y) {
        return x + y;
    };
    auto add4 = curry(add,4);
    std::cout << add4(3) << '\n'; //output: 7. (Ok)

}

解决方法

首先,您必须知道 currying是什么,或者在您的问题中,这特别是 partial application的情况(与currying有关,但略有不同).

基本上,它意味着使用一定数量的参数来减少函数,以创建另一个函数,其中一些参数的值是固定的.

我的例子,原始函数是add(x,y),它有两个参数x和y.通过将x设置为4来减少函数的arity add,并创建缩减函数add4(y),例如

add4(y)= add(x,y)其中x = 4

现在如何在您的c代码中实现这一目标?借助可变参数模板,可变参数函数和lambda函数.

Lambda functions是从C11开始的c.本质上它们是动态创建的匿名函数,可以存储在变量中.您在main()中创建add作为lambda:

auto add = [](auto x,auto y) {
 return x + y;
};

一个人通过模式[](参数列表){function-body}识别lambda;

注意:[]并不总是空的,请参阅“捕获变量”there,我们稍后会再回过头来看.

现在curry函数的目的是将这些lambdas函数func和一定数量的值中的一个作为参数,并通过将值按顺序分配给func的第一个参数来定义新函数.

variadic template参数Arguments … args允许使用“一定数量的参数”机制,它允许使用任意数量的类型作为模板参数调用模板(只要它们被称为编译时).所以在我们的例子中,传递的参数是4,因此Arguments … args将被int替换,而curry的实例将接受lambda和int作为参数.

如果我们看一下curry的代码,我们看到它本身只是一个lambda函数(它是一个variadic function,就像printf()),它的唯一目的是连接在实例化模板时其值已经修复的参数( args …)以及那些值作为参数传递给curried函数的人(rest …).

[=]符号是lambda函数的特殊捕获,它允许使用函数体中的所有局部变量(这里允许使用args).

所以要把它包起来,这是你的main函数中发生的事情:

>您创建一个名为add的变量,其中包含一个lambda
函数,取两个参数并添加它们.
>当您调用咖喱(添加,4)时,您实例化咖喱模板.

>第一个模板参数Function是add的类型(一个lambda采用两个int并返回一个int)
>第二个可变参数只包含一种类型:类型4,即int

实例化的咖喱函数看起来像这样

curry( (int,int)->(int) func,int arg){
    return [=](auto... rest) {return func(arg,rest...);};
}

请注意,由于自动和模板类型扣除,您永远不会看到这些类型.

>然后使用func = add和arg = 4调用此实例
>您将此实例化的结果存储在add4中,现在这一个带有一个参数的lambda.然后你可以调用add4 with 3作为参数(rest …是3),然后调用add(4,3)并返回7.

请注意,从技术上讲,您可以尝试使用多个参数调用add4,因为curried函数一个可变参数函数.只有当它在调用add时它没有这些额外参数的位置时,编译器才会失败(参见here)

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...