d不用异常.

import std.typecons : Option = Nullable, some = nullable;
alias unwrap = (x) => x.get;
//前面类似rust

Option!int most(string op)(const int[] nums) {
    if (nums.length) {
        int n = nums[0];
        foreach (m; nums[1 .. $]) {
            mixin("if (m " ~ op ~ " n) n = m;");
        }
        return some(n);
    } else {
        return typeof(return).init;
    }
}
alias min = most!"<";
alias max = most!">";

int find_gcd(const int[] nums) {
    import std.numeric : gcd;

    return gcd(nums.min.unwrap, nums.max.unwrap);
}

unittest {
    import std.exception : assertThrown;
    import core.exception : AssertError;

    assert(find_gcd([3, 5, 12, 15]) == 3);
    assertThrown!AssertError(find_gcd([]));
}

结论:
如果nums为空,程序会(一般)因不可抓错误而停止.
冗长解包清楚告诉我们程序在何处有错误因而停止.
因为Option!int和int不是同一类型,不能一起混合.如果忘记处理min/max错误情况,编译器会清楚告诉我们.
因为Option!TT类型不同,可有自己的错误处理如:

T unwrap_or(T)(Option!T opt, T alternate) { }

这样,来在空针时选择替代.
由于未用异常,可避免运行时成本,可不抛,BetterC也可用,也可有C接口,供其他语言使用.

int broken_find_gcd(const int[] nums) {
    import std.numeric : gcd;

    return gcd(nums.min, nums.max);
    // 错误`std.numeric.gcd`模板不能从参`!()(Option!int, Option!int)`推导函数,可用: ...
}

用这样:

int find_gcd(const int[] nums) nothrow {
    import std.numeric : gcd;

    return gcd(nums.min.unwrap, nums.max.unwrap);
}

如果d加个nothrow属性,也许很好.

posted @ 2021-09-10 15:20  zjh6  阅读(17)  评论(0)    收藏  举报  来源