php/e14genCorou.php

<?php

require_once('env.php');
outBegin('Generators and Coroutines');


function itRec($a, $p='') {
    if (! is_array($a)) {
        yield $p => $a;
    } else {
        $q = $p === '' ? '' : $p . ', ';
        foreach($a as $k => $v) {
            foreach( itRec($v, $q . $k) as $u => $v)
                yield "($p + $k) $u" => $v;
        }
    }
}

function itStack($arg) {
    $stack = [];
    $a = $arg;
    reset($a);
    $p = '';   

    while (true) {
        if (false === $c = current($a)) {
            if (null === $a = array_pop($stack))
                return;
            $p = substr($p, 0, strrpos($p, ','));
        } else {
            $k = key($a);
            next($a);
            if (is_array($c)) {
                array_push($stack, $a);
                $p .= ', ' . $k;
                $a = $c;
                reset($a);
            } else {
                yield substr($p . ', ' . $k, 2) => $c;
            }
        }
    }
}

function itOne($n) {
    $cont = ["itOne arg=$n", "one", "zwei" => "two", 9 => ['nine', 'neun']];
    $cx=0;
    outLi("itOne", ++$cx, "begin");
    foreach($cont as $k => $v) {
        if (! is_string($k)) {
            outLi("itOne$n", ++$cx, "foreach vor yield", $v);
            $o = yield $v;
        } else {
            outLi("itOne$n", ++$cx, "foreach vor yield $k =>", $v);
            $o = yield $k => $v;
        }
        outLi("itOne$n", ++$cx, "nach yield got", $o);
        if ($n == 1 and $o != null)
            foreach(itOne(2) as $r => $s) {
                outLi("itOne$n", ++$cx, "subiterator got $r =>", $s, ", yield+");
                yield "$r+" => (is_string($s) ? "$s+" : $s);
            }
    }
    outLi("itOne$n", ++$cx, "end");
}

outH('itRec recursive???');
out('recursive use of generators does not work! they have to pass the yield back throu the whole chain of calls');
outTB();
outTRH('#', 'key', 'current');
$cc = 0;
foreach( itRec([0, 'eins', [20, [210, 'zweihundertelf', [2120, 2121], 'zweihundertdreizehn'], 22], 'drei'
        , [40, [410]], 'fuenfSchluss']) as $k => $v)
    outTRD($cc++, $k, $v);
outTBEnd();
outH('itStack: simulating recursion by a manual stack of course works');
outTB();
outTRH('#', 'key', 'current');
$cc = 0;foreach( itStack([0, 'eins', [20, [210, 'zweihundertelf', [2120, 2121], 'zweihundertdreizehn'], 22], 'drei'
        , [40, [410]], 'fuenfSchluss']) as $k => $v)
    outTRD($cc++, $k, $v);
outTBEnd();

outH('itOne');
outOL();
outLi("main calls itOne(1) =", print_r($it = itOne(1), true));        
outLi("main it->valid()", $it->valid(), ", key()", $it->key(), ", current =", $it->current());
outLi("main it->next()", $it->next(), ", it->valid()", $it->valid(), ", key()", $it->key(), ", current =", $it->current());
outLi("main it->send([so send it])", $it->send(['so', 'send',  'it']), 
        ", it->valid()", $it->valid(), ", key()", $it->key(), ", current =", $it->current());
for ($i=0; $i < 7; $i++)
    outLi("main it->next()", $it->next(), ", it->valid()", $it->valid(), ", key()", $it->key(), ", current =", $it->current());
        
outEnd(__file__);
?>