d的自动柯里化

自动柯里化

f(a,b,c)f(a)(b)(c)调用.

template autocurry(alias what) {
    import std.traits;
    static if(Parameters!what.length)
        auto autocurry(Parameters!what[0] arg) {
            alias Remainder = Parameters!what[1 .. $];
            auto dg = delegate(Remainder args) {
                return what(arg, args);
            };

            static if(Remainder.length > 1)
                return &autocurry!dg;
            else
                return dg;
        }
    else
        alias autocurry = what;
}

int foo(int a, string b, float c) {
    import std.stdio; writeln(a, " ", b, " ", c);
    return 42;
}

string test() {
    import std.stdio; writeln("调用测试");
    return "无参";
}

void main() {
    import std.stdio;
    alias lol = autocurry!foo;
    writeln(lol(30)("lol")(5.3));

    auto partial = lol(20);
    partial("wtf")(10.5);

    alias t = autocurry!test;
    writeln(t());
}

想法很简单:如果有,根据剩余参数生成辅助函数,按闭包返回辅助函数地址,否则,只返回调用收集参数的闭包.递归处理多参,而外部静如仅返回原始函数来处理无参.

需要注意的语言特征:
1,同名模板.模板具有与模板同名的成员时(在本例中为autocurry),使用时会自动引用它.
2,扩展元组.调用(arg,args)时,内置元组的args自动扩展来创建完整参数列表.
3,各种自动返回(不指定返回类型的显式auto autocurry和隐式delegate关键字),只是转发返回的其他随机类型.
4,main函数中,

alias lol = autocurry!foo;
//lol为占位符,

示例.

int foo(int a, string b, float c) {
  import std.stdio;
  writeln(a, " ", b, " ", c);
  return 42;
}

 alias foo = autocurry!foo;
//用原foo重载自动柯里foo
//使用
void main() {
    foo(30)("lol")(5.3); // 柯里版
    foo(40, "cool", 103.4); // 原版
}
posted @ 2022-10-17 19:36  zjh6  阅读(27)  评论(0)    收藏  举报  来源