pure generators

Simen kjaeraas simen.kjaras at gmail.com
Wed May 12 17:25:37 PDT 2010


bearophile <bearophileHUGS at lycos.com> wrote:

> In few more years of D learning I hope to understand why D iteration is  
> designed that way, and if there are problems in it.

This has to do with D iteration being more designed towards mimicking
C arrays.
In D2, you'd use a range, and possibly have popFront return the new
(changed) range.

> In practice a generator like:
>
> (x for x in xrange(2,N) if all(x % i for i in xrange(2,x)))
>
> is kind of pure, because despite being lazy, the output it generates is  
> only influences by an input parameter N. So it's a Forward Range in D  
> speech.

Except that it also changes the input. It seems to me the python example
uses a closure, which, as Norman Adams allegedly said, "are a poor man's
objects." This closure must then change its associated state upon
iteration. (Granted, coroutines may be closer to the truth here, but I
have not quite grokked those yet, and the end result is basically the
same.)

> pure yield(int) primes(int stop) {
>     foreach (x; 2 .. stop) {
>         // an all() HOF can help here
>         bool all = true;
>         foreach (i; 2 .. x)
>             if (!(x % i)) {
>                 all = false;
>                 break;
>             }
>         if (all)
>             yield x;
>     }
> }

Here's an implementation that seems to work:


module foo;

import core.thread;
import std.stdio;

class YieldingFiber( T ) : Fiber {
   this( void function( ) fn ) {
     super( fn );
   }

   this( void delegate( ) fn ) {
     super( fn );
   }

   T call( ) {
     if ( auto o = super.call( ) ) {
       throw o;
     }
     return _value;
   }

   static void yield( T value ) {
     if ( auto p = cast( typeof( this ) )getThis( ) ) {
       p._value = value;
     }
     Fiber.yield( );
   }
private:
   T _value;
}

void primes( ) {
   int x = 2;
   while ( true ) {
     bool all = true;
     foreach ( i; 2 .. x ) {
       if ( !( x % i ) ) {
         all = false;
         break;
       }
     }
     if ( all ) {
       YieldingFiber!( int ).yield( x );
     }
     ++x;
   }
}

void main( ) {
   auto primes = new YieldingFiber!( int )( &primes );
   foreach ( i; 0..20 ) {
     writeln( primes.call( ) );
   }
}

> I am quite ignorant still about such topics of lazy pure functional  
> programming.

Welcome to the club!

-- 
Simen


More information about the Digitalmars-d mailing list