W3docs

yield from

Das Schlüsselwort yield from delegiert in PHP die Wertgenerierung an einen anderen Generator und ermöglicht das Verketten mehrerer Generatoren.

Einführung

yield from ist ein Ausdruck, mit dem ein Generator an ein anderes iterierbares Objekt delegieren kann – an einen anderen Generator, ein Array oder ein beliebiges Traversable. Anstatt manuell über die innere Quelle zu iterieren und jeden Wert einzeln weiterzugeben, schreibt man ein einzelnes yield from, und PHP leitet alle Werte (und Schlüssel) automatisch an den Aufrufer weiter.

Dies macht das Zusammensetzen von Generatoren einfach: Man kann aus kleinen, fokussierten Generatorfunktionen einen großen Wertstrom aufbauen, ohne dabei die gesamte Sequenz im Speicher zu materialisieren. Eingeführt in PHP 7.0 ist yield from der Standardweg, um verschachtelte Generatoren zu glätten.

Dieses Kapitel behandelt die grundlegende Syntax, den Umgang mit Schlüsseln, das Erfassen des Rückgabewerts eines delegierten Generators und wann Delegation das richtige Werkzeug ist.

Grundlegende Syntax

yield from erscheint innerhalb einer Generatorfunktion und wird von einem beliebigen iterierbaren Objekt gefolgt:

yield from $iterable; // generator, array, or Traversable

Hier ist ein minimales Beispiel, das zwei Generatoren zu einem Stream zusammenfasst:

<?php

function myGenerator()
{
  yield "Hello";
  yield "World";
}

function myOtherGenerator()
{
  yield "!";
}

function myCombinedGenerator()
{
  yield from myGenerator();
  yield from myOtherGenerator();
}

foreach (myCombinedGenerator() as $value) {
  echo $value . " ";
}

myCombinedGenerator() erzeugt keine eigenen Werte – es delegiert vollständig an die anderen beiden Generatoren. Der Aufruf liefert zuerst die Werte von myGenerator() und dann die von myOtherGenerator(), sodass die foreach-Schleife Folgendes ausgibt:

Hello World !

Es ist möglich, Delegation und normale yield-Anweisungen frei in derselben Funktion zu mischen:

<?php

function countToThree()
{
  yield 1;
  yield 2;
  yield 3;
}

function countToFive()
{
  yield from countToThree(); // delegates 1, 2, 3
  yield 4;                    // then yields its own values
  yield 5;
}

foreach (countToFive() as $value) {
  echo $value . " ";
}
// Output: 1 2 3 4 5

Delegation an Arrays und andere iterierbare Objekte

Die Quelle nach yield from muss kein Generator sein. Jedes Array oder Traversable funktioniert, was praktisch ist, um feste und lazy Sequenzen gemeinsam zu glätten:

<?php

function items()
{
  yield from ['apple', 'banana']; // an array
  yield from ['cherry'];
}

foreach (items() as $item) {
  echo $item . "\n";
}
// Output:
// apple
// banana
// cherry

Umgang mit Schlüsseln

yield from bewahrt die Schlüssel des inneren iterierbaren Objekts, nicht nur die Werte. Dies ist die häufigste Fehlerquelle: Schlüssel werden nicht neu nummeriert, sodass zwei delegierte Quellen doppelte Schlüssel erzeugen können.

<?php

function inner()
{
  yield 'a' => 1;
  yield 'b' => 2;
}

function outer()
{
  yield from inner();
  yield 'c' => 3;
}

foreach (outer() as $key => $value) {
  echo "$key => $value\n";
}
// Output:
// a => 1
// b => 2
// c => 3

Da Schlüssel unverändert übernommen werden, sollte man sich beim Delegieren an ganzzahlig indizierte Quellen nicht auf eine durchgehende Sequenz 0, 1, 2, … verlassen — man kann die Werte mit iterator_to_array($gen, false) in ein Array einlesen, wenn eine Neuindizierung benötigt wird.

Rückgabewert des inneren Generators erfassen

Ein delegierter Generator kann einen abschließenden Wert returnen (getrennt von den Werten, die er liefert). Der yield from-Ausdruck wertet sich zu diesem Rückgabewert aus, den man einer Variablen zuweisen kann:

<?php

function inner()
{
  yield 1;
  yield 2;
  return 'done';
}

function outer()
{
  $result = yield from inner();
  echo "Inner returned: $result\n";
  yield 3;
}

foreach (outer() as $value) {
  echo "Value: $value\n";
}
// Output:
// Value: 1
// Value: 2
// Inner returned: done
// Value: 3

Der return-Wert des inneren Generators wird von yield from erfasst – er wird nicht an die foreach-Schleife weitergeleitet. Nur die gelieferten Werte (1, 2, 3) erreichen den Verbraucher.

Wann yield from eingesetzt werden sollte

yield from ist die richtige Wahl, wenn man:

  • Generatoren zusammensetzen möchte — eine Pipeline aus kleinen, zweckgerichteten Generatorfunktionen aufbauen, statt einer großen Funktion.
  • Verschachtelte Strukturen glätten möchte — rekursiv Bäume oder verschachtelte Arrays durchlaufen und einen einzelnen flachen Wertstrom ausgeben.
  • Speichereffizient bleiben möchte — Werte fließen lazy, einen nach dem anderen, sodass die vollständige Sequenz nie im Speicher gehalten wird.

Im Vergleich zum manuellen Weiterleiten (foreach ($inner as $v) { yield $v; }) ist yield from kürzer, bewahrt Schlüssel automatisch und leitet den Rückgabewert des inneren Generators weiter – daher sollte es bevorzugt werden, wann immer an ein anderes iterierbares Objekt delegiert wird.

Verwandte Themen

Übungen

Übung
Was ist der primäre Verwendungszweck der 'yield from'-Anweisung in PHP?
Was ist der primäre Verwendungszweck der 'yield from'-Anweisung in PHP?
Was this page helpful?