Impressed

Artur Skawina art.08.09 at gmail.com
Fri Jul 27 12:17:58 PDT 2012


On 07/27/12 20:47, Stuart wrote:
> On Friday, 27 July 2012 at 15:09:38 UTC, Graham Fawcett wrote:
>> On Friday, 27 July 2012 at 13:10:46 UTC, Stuart wrote:
>>> On Friday, 27 July 2012 at 03:00:25 UTC, Brad Anderson wrote:
>>>>
>>>> D equivalent: iota(0, int.max, 2).map!(a => /* do something with even numbers */)();
>>>
>>> I think you're missing the point. The purpose isn't to generate a sequence of numbers, but to illustrate how the Yield keyword is used in VB.NET. Sure, getting a sequence of numbers may be straightforward, but what about a lazy-populated list of all files on a computer? That can be done using Yield - and more importantly, WRITTEN like a normal synchronous function. Let's see you do that with map.
>>
>> That's easy:
>>
>>   [...elided code...]
>>   auto entries = dirEntries(BASE_DIR, SpanMode.breadth);
> 
> Ah, but that depends upon the pre-existence of the dirEntries() function. I think perhaps you're missing the point - which is that "Yield" allows you to WRITE a function synchronously which will then be executed lazily, as an iterator. What you have demonstrated there is USING a lazy function. How would I write, in D, a function that would lazily assemble some data and return it as a lazy collection? I mean, without calling existing lazy functions.

A more or less direct translation of your original example would be:

   auto infiniteSequence1(T, S)(T startValue, S step) {
      struct IS {
         auto opApply(scope int delegate(ref T) yield) {
            while (1)
               if (auto r = yield(startValue))
                  return r;
               else
                  startValue += step;
         }
      }
   
      return IS();
   }

   void main() {
      import std.stdio;
      foreach(n; infiniteSequence(2, 2)) {
         writeln(n);
         if (n>13)
            break;
      }
   }

and a D-style range based version could look like this:

   auto infiniteSequence(T, S)(T startValue, S step) {
      static struct IS {
         T startValue;
         S step;

         enum empty = false;
         @property ref front() { return startValue; }
         void popFront() { front += step; }
      }

      return IS(startValue, step);
   }

which both are as lazy as it gets. Returning direntries would be
done similarly. Is this just about the syntax (which isn't much
different)?

artur


More information about the Digitalmars-d mailing list