我尝试编译以下代码:
import std.algorithm;
void main()
{
string[] x = ["ab", "cd", "ef"]; // 'string' is same as 'immutable(char)[]'
string space = " ";
char z = joiner( x, space ).front(); // error
}
编译dmd
以错误结束:
test.d(8): Error: cannot implicitly convert expression (joiner(x,space).front()) of type dchar to char
将char z
更改为dchar z
会修复错误消息,但我很感兴趣,为什么它首先出现。
为什么joiner(string[],string).front()
的结果是dchar而不是char?
答案 0 :(得分:11)
所有字符串都被视为dchar
的范围。这是因为dchar
保证是单个代码点,因为在UTF-32中,每个代码单元都是代码点,而在UTF-8(char
)和UTF-16({{ 1}}),每个代码点的代码单元数量不同。因此,如果您在单个wchar
或char
上运行,则您将使用字符而不是整个字符进行操作,这将非常糟糕。如果您对unicode了解不多,我建议您阅读Joel Spolsky的this article。它解释得很好。
在任何情况下,由于对单个wchar
和char
进行操作没有意义,因此将wchar
和char
的字符串视为{{的范围1}}(wchar
是dchar
),这意味着就范围而言,它们没有ElementType!string
(dchar
是length
- { {1}}需要用于获取其长度),不可切片(hasLength!string
为false
),且不可转换(walkLength
为hasSlicing!string
) 。这也意味着从任何类型的字符串构建新范围的任何内容都将产生false
的范围。 isRandomAccess!string
就是其中之一。有一些函数可以理解unicode和特殊情况字符串的效率,利用长度,切片和索引尽可能,但除非它们的结果最终是原始的一部分,否则它们返回的任何范围都必须被制作false
s。
因此,任何字符范围的dchar
始终为joiner
,dchar
将始终弹出完整的代码点。
如果您对范围知之甚少,我建议您阅读this。这是关于D的书中的一章,它是在线的,目前是关于范围的最佳教程。我们真的应该在dlang.org上得到一篇关于范围的适当文章(包括它们如何使用字符串),但还没有人编写它。无论如何,你需要至少掌握一系列范围才能使用很多D的标准库(特别是std.algorithm),因为它非常大量地使用它们。