bearophile <[email protected]> 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

Reply via email to