代码之家  ›  专栏  ›  技术社区  ›  minerals

为什么d中的char[]数组没有引发类型result的[]运算符重载?

d
  •  0
  • minerals  · 技术社区  · 5 年前

    我在玩 std.range std.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] ,它可以工作,但我希望错误消息更具揭示性。

    1 回复  |  直到 5 年前
        1
  •  1
  •   Adam D. Ruppe    5 年前

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

    好吧,为什么?这就是D社区所说的“自动解码”。char[]是一个utf-8字符串。phobos试图提供帮助,将这些utf-8序列转换为一系列dchars,这些dchars表示unicode代码点。

    utf-8序列具有可变长度。大多数英文文本都有一个字节对应于屏幕上的一个字符,但对于其他语言来说,这通常是不正确的。例如,重音符号可以由各种两字节或三字节序列表示。(而且在某些情况下,它变得更加复杂,各种相同的视觉表示具有不同的内部表示-std.uni.bygrapheme是火卫一图书馆的一部分,旨在帮助实现这一点)

    无论如何,phobos-再次尝试帮助,尽管我们基本上普遍认为这是一个错误的设计,现在回头看-试图将这些可能的多字节序列压缩为一个dchar,每次循环。如果不扫描到该点的整个字符串,它就无法知道第n个dchar在哪里(因为每个dchar可能有不同的长度,您必须检查它才能知道大小),因此它无法廉价地做到这一点。

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

    这个 .array 函数只是分配一个大的缓冲区,并做所有的解码工作,而不是按需,因此允许随机访问…但是如果你只需要看一点结果的话,可能不需要花费内存和处理时间。