foreach iterator with closure

Ali Çehreli acehreli at yahoo.com
Sun Jun 28 04:06:00 UTC 2020


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



More information about the Digitalmars-d-learn mailing list