yield from
La palabra clave yield from en PHP delega la generación de valores a otro generador, permitiendo encadenar múltiples generadores de forma eficiente.
Introducción
yield from es una expresión que permite a un generador delegar a otro iterable — otro generador, un array o cualquier Traversable. En lugar de iterar sobre la fuente interna y volver a producir cada elemento manualmente, se escribe un solo yield from y PHP reenvía todos sus valores (y claves) al llamador automáticamente.
Esto facilita la composición de generadores: puedes construir un flujo grande de valores a partir de pequeñas funciones generadoras enfocadas sin materializar nunca toda la secuencia en memoria. Introducido en PHP 7.0, yield from es la forma estándar de aplanar generadores anidados.
Este capítulo cubre la sintaxis básica, cómo se manejan las claves, cómo capturar el valor de retorno de un generador delegado y cuándo la delegación es la herramienta adecuada.
Sintaxis básica
yield from aparece dentro de una función generadora y va seguido de cualquier iterable:
yield from $iterable; // generator, array, or TraversableAquí hay un ejemplo mínimo que combina dos generadores en un solo flujo:
<?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() no produce ningún valor propio — delega completamente a los otros dos generadores. Al llamarlo, primero produce los valores de myGenerator() y luego los de myOtherGenerator(), por lo que el foreach imprime:
Hello World !Puedes mezclar libremente la delegación con sentencias yield normales en la misma función:
<?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 5Delegación a arrays y otros iterables
La fuente tras yield from no tiene que ser un generador. Cualquier array o Traversable funciona, lo que es útil para aplanar secuencias fijas y perezosas juntas:
<?php
function items()
{
yield from ['apple', 'banana']; // an array
yield from ['cherry'];
}
foreach (items() as $item) {
echo $item . "\n";
}
// Output:
// apple
// banana
// cherryCómo se manejan las claves
yield from conserva las claves del iterable interno, no solo los valores. Este es el error más común: las claves no se renumeran, por lo que dos fuentes delegadas pueden producir claves duplicadas.
<?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 => 3Dado que las claves se mantienen tal cual, no dependas de una secuencia continua 0, 1, 2, … al delegar a fuentes con claves enteras — recopila los valores en un array con iterator_to_array($gen, false) si necesitas reindexarlos.
Capturar el valor de retorno del generador interno
Un generador delegado puede return un valor final (separado de los valores que produce). La expresión yield from evalúa a ese valor de retorno, que puedes asignar a una variable:
<?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: 3Ten en cuenta que el valor de return del generador interno es capturado por yield from — no se reenvía al bucle foreach. Solo los valores producidos (1, 2, 3) llegan al consumidor.
Cuándo usar yield from
Usa yield from cuando quieras:
- Componer generadores — construir un pipeline a partir de pequeñas funciones generadoras de un solo propósito en lugar de una función grande.
- Aplanar estructuras anidadas — recorrer árboles o arrays anidados de forma recursiva y emitir un único flujo plano de valores.
- Mantener la eficiencia de memoria — los valores fluyen de forma perezosa, uno a la vez, por lo que nunca se mantiene toda la secuencia en memoria.
Comparado con volver a producir manualmente (foreach ($inner as $v) { yield $v; }), yield from es más corto, preserva las claves automáticamente y reenvía el valor de retorno del generador interno — así que prefiérelo siempre que estés delegando a otro iterable.
Temas relacionados
- yield — la base de los generadores en PHP.
- foreach loop — cómo se consumen los valores de los generadores.
- PHP functions y return — los bloques de construcción detrás de las funciones generadoras.