1unitedpower: Im Sting alles mit (xxx) ersetzten

Beitrag lesen

Wärst Du bereit dazu, es noch etwas ausführlicher zu erklären? Dann könnten wir es ins Wiki für PHP unter dem Abschnitt "Generatoren" aufnehmen.

Ein Parser ist zu umfangreich um als Einführungsbeispiel zu dienen. Ich würde kleiner anfangen und zeigen, wie man ein paar der herkömmlichen Array-Funktionen mit Generatoren nachbauen kann. Ein wenig Inspiration:

Vorab eine kleine Helferfunktion:

function log(iterable $source) : void
{
    foreach ($source as $value) {
        echo "$value ";
    }
}

log([1,2,3]); // 1 2 3

Zwei iterables aneinander ketten:

function concat(iterable $first, iterable $second) : Generator
{
    foreach ($first as $key => $value) {
        yield $key => $value;
    }
    foreach ($second as $key => $value) {
        yield $key => $value;
    }
}

log(concat([1,2,3], [4,5,6])); // 1 2 3 4 5 6

Ein iterable filtern:

function filter(callable $f, iterable $source) : Generator
{
    foreach ($source as $key => $value) {
        if ($f($value)) {
            yield $key => $value;
        }
    }
}

log(filter(function ($n) { return $n mod 2 === 0 }, [1,2,3,4,5,6]); // 2 4 6

Jedes Element aus einem iterable auf ein neues Element abbilden:

function map(callable $f, iterable $source) : Generator
{
    foreach ($source as $key => $value) {
        yield $key => $f($value);
    }
}

log(map(function ($n) { return $n mod 2; }, [1,2,3,4,5,6])); // 1 0 1 0 1 0

Werte akkumulieren:

function fold(mixed $start, callable $f, iterable $source) : mixed
{
    $accumulator = $start;
    foreach ($source as $key => $value) {
        $accumulator = $f($accumulator, $value);
    }
    return $accumulator;
}

log(fold(0, function ($a, $b) { return $a + $b; }, [1,2,3,4,5,6])); // 21

Werte akkumulieren und Zwischenschritte ausgeben:

function scan(mixed $start, callable $f, iterable $source) : Generator
{
    $accumulator = $start;
    foreach ($source as $key => $value) {
        $accumulator = $f($accumulator, $value);
        yield $key => $accumulator;
    }
}
log(fold(0, function ($a, $b) { return $a + $b; }, [1,2,3,4,5,6])); // 1 3 6 10 15 21