7

我尝试编译以下代码:

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 zdchar z确实修复了错误消息,但我很感兴趣它为什么首先出现。

为什么结果joiner(string[],string).front()是 dchar 而不是 char?

(文档http://dlang.org/phobos/std_algorithm.html#joiner对此没有任何内容)

4

1 回答 1

11

所有字符串都被视为dchar. 这是因为 adchar保证是单个代码点,因为在 UTF-32 中,每个代码单元都是一个代码点,而在 UTF-8 ( char) 和 UTF-16 ( wchar) 中,每个代码点的代码单元数量是不同的。因此,如果您在单个chars 或wchars 上进行操作,您将在字符片段而不是整个字符上进行操作,这将是非常糟糕的。如果您对 unicode 不太了解,我建议您阅读Joel Spolsky 的这篇文章。它很好地解释了事情。

在任何情况下,因为对单个chars 和wchars 进行操作没有意义,所以 and 的字符串charwchar视为dchar( ElementType!stringis dchar) 的范围,这意味着就范围而言,它们没有length( hasLength!stringis false-walkLength需要使用获取它们的长度),不可切片(hasSlicing!stringis false),不可索引(isRandomAccess!stringis false)。这也意味着从任何类型的字符串构建新范围的任何内容都将导致范围为dchar.joiner就是其中之一。有一些函数可以理解 unicode 和特殊情况字符串以提高效率,尽可能利用长度、切片和索引,但除非它们的结果最终是原始的切片,否则它们返回的任何范围都必须进行dchars 。

因此,front任何范围的字符都将始终是dchar,并且popFront总是会弹出一个完整的代码点。

如果您对范围不太了解,我建议您阅读内容。这是一本关于 D 的书中的一章,它是在线的,是目前我们所拥有的关于范围的最佳教程。我们真的应该在dlang.org上获得一篇关于范围(包括它们如何与字符串一起工作)的适当文章,但还没有人开始编写它。无论如何,您至少需要对范围有基本的了解才能使用很多 D 的标准库(尤其是 std.algorithm),因为它非常频繁地使用它们。

于 2012-09-05T20:20:00.457 回答