gpt4 book ai didi

range - 尝试实现 zipWith

转载 作者:行者123 更新时间:2023-12-05 01:05:39 26 4
gpt4 key购买 nike

我正在尝试实现经典的高阶范围 zipWith如下

import std.traits: allSatisfy;
import std.range: isInputRange;

auto zipWith(fun, Ranges...)(Ranges ranges) if (Ranges.length >= 2 && allSatisfy!(isInputRange, Ranges))
{
import std.range: zip;
return zip(ranges).map!fun;
}

但是
unittest
{
auto x = [1, 2, 3, 4, 5];
zipWith!((a, b) => a + b)(x, x);
}

因错误而失败
template algorithm_ex.zipWith cannot deduce function from argument types !((a, b) => a + b)(int[], int[]), candidates are: (d-dmd-unittest)
algorithm_ex.zipWith(fun, Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges))

我不明白为什么。有线索吗?

更新 :

在 Cyber​​Shadows 很好的答案之后,我现在有了
import std.traits: allSatisfy;

/** Zip $(D ranges) together with operation $(D fun).
TODO: Simplify when Issue 8715 is fixed providing zipWith
*/
auto zipWith(alias fun, Ranges...)(Ranges ranges) if (Ranges.length >= 2 && allSatisfy!(isInputRange, Ranges)) {
import std.range: zip;
import std.algorithm: map;
import std.functional: binaryFun;
static if (ranges.length == 2)
return zip(ranges).map!(a => binaryFun!fun(a.expand));
else if (ranges.length >= 3)
return zip(ranges).map!(a => naryFun(a.expand));
else
static assert(false, "Need at least 2 range arguments.");
}
unittest {
auto x = [1, 2, 3];
import std.array: array;
assert(zipWith!"a+b"(x, x).array == [2, 4, 6]);
assert(zipWith!((a, b) => a + b)(x, x).array == [2, 4, 6]);
assert(zipWith!"a+b+c"(x, x, x).array == [3, 6, 9]);
}

是否可以扩展它以通过字符串支持 nary fun,例如 zipWith!"a+b+c"(x,x,x) ?我问特别是因为我注意到有 naryFun 的代码在 std.functional 中,但已注释掉。

最佳答案

  • 您必须声明 fun模板参数作为 alias参数,否则声明为类型参数:
    auto zipWith(alias fun, Ranges...)( // ...
  • 您需要导入 std.algorithmmap .
  • std.range.zip将返回 std.typecons.Tuple 的范围,它不会自动扩展为 lambda 的两个参数。您需要显式扩展元组。

  • 固定代码:
    import std.traits: allSatisfy;
    import std.range: isInputRange;
    import std.algorithm: map;

    auto zipWith(alias fun, Ranges...)(Ranges ranges) if (Ranges.length >= 2 && allSatisfy!(isInputRange, Ranges))
    {
    import std.range: zip;
    return zip(ranges).map!(t => fun(t.expand));
    }

    unittest
    {
    auto x = [1, 2, 3, 4, 5];
    zipWith!((a, b) => a + b)(x, x);
    }

    Is it possible to extend it to support nary fun's via strings, like zipWith!"a+b+c"(x,x,x)?



    我不明白为什么不:
    import std.string;

    private string genNaryFun(string fun, V...)()
    {
    string code;
    foreach (n, v; V)
    code ~= "alias values[%d] %s;".format(n, cast(char)('a'+n));
    code ~= "return " ~ fun ~ ";";
    return code;
    }

    template naryFun(string fun)
    {
    auto naryFun(V...)(V values)
    {
    mixin(genNaryFun!(fun, V));
    }
    }

    unittest
    {
    alias naryFun!"a + b + c" test;
    assert(test(1, 2, 3) == 6);
    }

    关于range - 尝试实现 zipWith,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21210867/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com