【问题标题】:Cannot Slice Take!R from std.range in D?不能从 D 中的 std.range 切片 Take!R?
【发布时间】:2012-10-22 15:47:02
【问题描述】:

我正在尝试使用切片运算符从 std.range 获取取函数返回值的切片。我的代码:

auto tempChunk = ['a', 'b', 'c', 'd'];
auto a = tempChunk.take(3);
writeln(a[0..2]);

As Take!R 在这种情况下只是 char[] 的别名,我希望它能够编译。但是,编译器告诉我Take!(char[]) cannot be sliced with []。再举个例子:

int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 
auto s = arr.take(5);
writeln(s[0..4]);

这将毫无问题地编译和运行,打印 [1, 2, 3, 4, 5]。在这一点上,我完全不明白为什么第一个例子不起作用,而第二个例子起作用。

【问题讨论】:

    标签: d phobos


    【解决方案1】:

    take 模板使用 hasSlicing 来确定是否可以返回输入切片而不是 Take!R 结构。检查实际的返回类型使其更加清晰:

    import std.range, std.stdio;
    
    void main()
    {
        auto chararr = ['a', 'b', 'c', 'd'];
        auto a = chararr.take(3);
        writeln( typeid(typeof(a)) );
    
        auto intarr = [ 1, 2, 3, 4 ];  
        auto b = intarr.take(3);
        writeln( typeid(typeof(b)) );
    }
    
    // Output:
    // std.range.Take!(char[]).Take
    // int[]
    

    hasSlicing 被明确指示为所有“窄字符串”返回 false - 那些元素可能不代表单个字符,而是一个代码点(基于 char 和 wchar那些)。

    现在,我的猜测从这里开始,但我想这样做是为了防止使用切片意外创建格式错误的 UTF-8 和 Co 字符串。如果您对 char[] 没有任何实际需求,最好使用 dchar[]。

    【讨论】:

    • 谢谢,这样就搞定了。但是,Take 结构定义了一个 opIndex,但是当我尝试 writeln(a[0]); 时,它不起作用。这是什么原因?
    • 它只为 RandomAccessRange 定义 opIndex,而窄字符串则没有。老实说,我无法理解这个基本原理,因为窄字符串实际上通过本机切片用作随机访问代码点范围。这是个好问题。
    • P.S.我建议使用 d 标签或同时使用 d 和 d2,因为订阅 d feed 的人更多。
    • @Михаил Страшун 所有字符串都被明确视为 dchar 的范围,因为对一系列代码单元进行操作通常没有意义,而对窄字符串进行切片操作的是 chars 或 wchars,而不是 dchars,所以除非您知道您正在明确地处理字符串,否则切片无法工作,即使那样,它通常也无法在 O(1) 中完成,因为您需要首先找到有效代码点的索引。这个答案stackoverflow.com/a/12289147/160887 和这个答案stackoverflow.com/a/6401889/160887 都讨论了这个问题。如果需要,请随时发布新问题。
    • @JonathanMDavis 是的,我知道推理,但问题是实际上在某些情况下字符串被视为代码点范围,我很难建立一致的设计 pciture :)(我有已经在 D.learn 中启动了一个相关线程)
    猜你喜欢
    • 2015-04-25
    • 2014-05-23
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 2018-07-18
    • 2021-10-30
    • 2021-11-03
    相关资源
    最近更新 更多