为什么在 D 中没有使用 char[] 数组抛出 Result 类型的 [] 运算符重载?

Why No [] operator overload for type Result is thrown with char[] array in D?

我在玩 std.rangestd.algorithm 并遇到了以下问题。

int[] arr1 = [-1, 1, 2, 3, 5, 8];
char[] arr2 = ['a', 'b', 'c', 'd', 'e'];

auto res1 = arr.enumerate.find!(t => t[0] == 4);
auto res2 = arr1.enumerate.find!(t => t[0] == 4);

assert(typeof(res1).stringof == typeof(res2).stringof);

现在,我想访问 find 的结果,它是 [Tuple!(ulong, "index", int, "value")(4, 5), Tuple!(ulong, "index", int, "value")(5, 8)]

writeln(res1[0][1]); // 5

我正确地得到 5。现在,如果我对 res2 做同样的事情,它等于 [Tuple!(ulong, "index", dchar, "value")(4, 'e')]

writeln(res2[0][1]); // Error: no [] operator overload for type Result

抛出异常(挠头)。你能解释一下为什么它适用于 int[] 数组而不适用于 char[] 吗?

更新:如果我调用 res2.array[0][1],它可以工作,但我希望错误消息更能说明问题。

原因是 Phobos 库认为 int[] 是随机访问,而 char[] 只是顺序访问,因此没有运算符。

好的,这是为什么呢?这就是D界所说的"autodecoding"。 char[] 是一个 UTF-8 字符串。 Phobos 试图提供帮助,将这些 UTF-8 序列转换为一系列代表 Unicode 代码点的 dchars。

UTF-8 序列长度可变。大多数英文文本将有一个字节对应屏幕上的一个字符,但对于其他语言通常情况并非如此。例如,重音标记可以由各种两字节或三字节序列表示。 (在某些情况下它变得更加复杂,各种相同的视觉表示具有不同的内部表示 - std.uni.byGrapheme 是 Phobos 库的一部分,旨在帮助解决这个问题)

无论如何,Phobos - 再次试图提供帮助,即使我们现在回想起来基本上普遍认为这是一个错误的设计 - 试图在循环时一次将那些可能的多字节序列压缩到一个 dchar。因为它无法知道第 N 个 dchar 在哪里而不扫描整个字符串直到那个点(因为每个 dchar 可能具有不同的长度并且您必须检查它才能知道大小),它不能便宜地做到这一点。

由于 [] 运算符应该是廉价的,O(1) 常数时间(和常数内存)操作,此实现太复杂而无法向接口确认,您反而得到了错误。

.array 函数只分配一个大缓冲区并预先完成所有解码工作,而不是按需进行,因此允许随机访问...但以内存和处理时间为代价如果您只需要查看一点结果,则可能没有必要。