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
指令编译
的,且不可赋值
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现