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行只分配通过.filter3个元素,而如果急切创建了中间结果数组,需要为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指令编译的,且不可赋值.

posted @   zjh6  阅读(23)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示