【问题标题】:How to make Range work with foreach statement如何使 Range 与 foreach 语句一起使用
【发布时间】:2012-07-22 20:01:47
【问题描述】:

我有以下范围:

struct Range {
  uint data;

  @property{
    bool empty() { return false; }
    uint front() { return data; }
    void popFront() { data = data * 2 + 1; }
  }
}

尝试使用它, foreach(c; Rnage()){ /*...*/ } 有效,但使用 foreach(i, c; Range()){ /*...*/ } 我得到:

Error: cannot infer argument types

我需要i,就像foreach(i, v; [1,2,3,4]){ } 一样。

【问题讨论】:

    标签: foreach range d


    【解决方案1】:

    范围不支持语法

    foreach(i, c; range)
    

    虽然在简单的情况下这似乎很明显,但该索引甚至应该是什么取决于范围的类型并且并不总是有意义的。因此,foreach 不会自动提供索引的计数器,范围也无法提供。

    不过,感谢tuple unpacking with foreach,您可以在您的范围内使用std.range.sequence std.range.zip

    foreach (i, e; zip(sequence!"n"(), range))
    {
    }
    

    顺便说一句,您不应该将popFront 标记为@property。这没有任何意义。 popFront 不接受任何参数,也不返回任何值。它根本不像一个变量。属性的重点是具有像变量一样起作用的函数。如果/当-property 的实现完全整理并成为正常行为(目前它相当有问题,这就是为什么它目前是一个单独的开关的部分原因),popFront 将无法像你一样使用定义它。

    【讨论】:

      【解决方案2】:

      如果您使用opApply 来实现范围,您可以为无索引样式和有索引样式重载一个版本:

      struct Range {
          int opApply(int delegate(int) action){
              uint data=0;
              while(true){
                  action(data);
                  data=data*2+1;
              }
              return 0;
          }
      
          int opApply(int delegate(uint,int) action){
              uint i=0;
              foreach(element;this){
                  action(i++,element);
              }
              return 0;
          }
      }
      

      【讨论】:

      • 它不适用于opApply 的范围。一个类型可以实现范围原语和opApply,但opApply 与范围无关,它不会使类型与基于范围的函数一起使用。这只是用foreach 定义迭代的一种方式。所以,关于 D 如何使用术语范围,说你的结构在这里是一个范围是完全用词不当的。
      猜你喜欢
      • 1970-01-01
      • 2012-08-10
      • 2020-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多