On 6/27/20 8:19 PM, Denis wrote:

> Is it possible to write an iterator

It is arguable whether D's ranges are iterators but if nouns are useful, we call them ranges. :) (Iterators can be written in D as well and then it would really be confusing.)

>    struct letters {
>      string str;
>      int pos = 0;
>      char front() { return str[pos]; }
>      void popFront() { pos ++; }
>      bool empty() {
>        if (pos == 0) writeln(`BEGIN`);
>        else if (pos == str.length) writeln("\nEND");
>        return pos == str.length; }}
>
>    void main() {
>      foreach (letter; letters(`hello`)) {
>        write(letter, ' '); }
>      writeln(); }
>
> The obvious problems with this code include:
>
> (1) The user can pass a second argument, which will set the initial
> value of pos.

That problem can be solved by a constructor that takes a single string. Your BEGIN code would normally go there as well. And END goes into the destructor:

struct letters {
    this(string str) {
        this.str = str;
        this.pos = 0;  // Redundant
        writeln(`BEGIN`);
    }

    ~this() {
        writeln("\nEND");
    }

    // [...]
}

Note: You may want to either disallow copying of your type or write copy constructor that does the right thing:

  https://dlang.org/spec/struct.html#struct-copy-constructor

However, it's common to construct a range object by a function. The actual range type can be kept as an implementation detail:

struct Letters {  // Note capital L
  // ...
}

auto letters(string str) {
  // ...
  return Letters(str);
}

struct Letter can be a private type of its module or even a nested struct inside letters(), in which case it's called a "Voldemort type".

Ali

Reply via email to