d结果类型的目的
原文
 举例:
import std;
void main()
{
    auto c = "a|b|c|d|e".splitter('|');
    c.writeln;
    string[]e=["a","b","c","d","e"];
    assert(c.equal(e));
    typeof(c).stringof.writeln;
}
//打印
["a", "b", "c", "d", "e"]
Result
Result类型的目的?用作通用区间吗?它似乎只会引起问题.如,即使该类型有相同本质函数,也不能赋值或转换结果类型到区间中:
string[] c = "a|b|c|d|e".splitter('|'); //失败
string[] d = cast(string[])"a|b|c|d|e".splitter('|'); // 也失败
但,如果要执行集合操作呢?
c[] ~= "lolno";
 //因为没有为`Result`定义`[]`,失败
该类型的意义?不能转换,不能向量运算,似乎只是不必要的泛化.
此外,还可确认c的每个成员都是串,它只是不能转换为原始类型数组的通用区间模板.
该结果类型是提供原串的懒计算区间的内部类型.也即,直到开始取每个元素,不分配数组及实际搜索|符.
它返回窗口到原串,并(通过切片)一次构建每个窗口一个元素.
 因此,你说"转换为区间"时,试转换为串数组时,你没有正确按区间说明串[]类型,结果类型是个区间,且是个串区间.它不是数组.如果想要数组,可用分配数组来保存所有切片的分割(split)函数.
对,因为结果不是数组.追加是数组运算,不是区间运算.
 关键是要在原始输入区间内懒计算,使用该构建块,可创建数组等等,这些都不需要分配更多空间来保存数组.
它是表示懒遍历元素区间的隐藏类型.
 你把数组和区间搞混了,区间不是指定的类型,它是(表现得像区间的)类型.每个"结果(Result)"都有它自己唯一的类型(可说,只显示为"结果"而不把隐藏类型区分开,是编译器错误),所以不能把它赋值回数组.
 可用std.array.array来创建数组,或使用急切地创建结果的函数来代替懒结果(上例中,用std.string.split代替.splitter),或使用std.algorithm.copy来把懒区间内容复制到数组中:
string[] c = "a|b|c|d|e".splitter('|').dup;
string[] c = "a|b|c|d|e".split('|');
// : .copy期望提前准备足够空间
string[] result = new string[5];
"a|b|c|d|e".splitter('|').copy(result);
它把多个区间操作连接成流水线:
string[] c = "a|b|c|d|e".splitter('|')
    .filter!(c => c >= 'b' && c <= 'd')
    .map!(c => c+1)
    .array;
因为区间是懒迭代的,所以.array行只分配通过.filter的3个元素,而如果急切创建了中间结果数组,需要为5个元素分配空间,然后丢弃其中的2个元素.
 这样想,中间Result区间就像长管道的中间部分;不能在不破坏它,就从管道中间得到东西,需要先用(如.array,.copy等)接收器来终止管道.
区间并不提供你所找的API,它提供了3个(front,popFront,empty)方法:
 不提供追加,如果想追加或随机访问,使用数组:
auto c = "a|b|c|d|e".split('|');
static assert(is(typeof(c) == string[]));
// 或
auto c2 = "a|b|c|d|e".splitter('|').array;
//区间转数组.
不需要编写包装器.只需添加'.array'到管道尾,就可以了.
注意,有些特殊函数可保持懒,如链(chain).
import std;
void main()
{
    auto c = "a|b|c|d|e".splitter("|").chain(["f"]);
    string[] e = ["a", "b", "c", "d", "e", "f"];
    assert(c.equal(e));
}
按整体使用区间,这种设计结构是首选的(像管道一样端到端).Walter有篇关于隐藏类型的古老文章,这是D的基础,请阅读它.对理解区间的人而言,D的区间是非常强大的.
 下面的区间算法,在调用它的两个值之间交替.
auto alternate(T)(T a, T b) {
    //函数返回下面的嵌套结构对象
    struct MyResult {
        bool useB = false;
        enum empty = false; // 无穷
        T front() {
            return useB ? b : a;
        }
        void popFront() {
            // 翻转
            useB = !useB;
        }
    }
    // 返回带useB单个成员的构对象
    return MyResult();//a,b为实际参数
}
import std;
void main() {
    auto myRange = alternate(42, 7);
    pragma(msg, typeof(myRange));
    //编译时打印`MyResult`.
    const expected = [ 42, 7, 42, 7, 42 ];
    assert(myRange.take(5).equal(expected));
}
不同模板实例化是不同类型.如,如果我用两个"long"值调用"alternate",alternate!int(如上面的代码实例化的)和alternate!long会有不同的MyResult结构类型.
 尽管功能相同,但可能是用非常不同的CPU指令编译的,且不可赋值.
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号