yield from
A palavra-chave yield from no PHP delega a geração de valores a outro gerador, permitindo encadear múltiplos geradores de forma eficiente.
Introdução
yield from é uma expressão que permite a um gerador delegar para outro iterável — outro gerador, um array ou qualquer Traversable. Em vez de percorrer a fonte interna com um loop e re-yielding cada item manualmente, você escreve um único yield from e o PHP encaminha todos os seus valores (e chaves) para o chamador automaticamente.
Isso facilita a composição de geradores: você pode construir um grande fluxo de valores a partir de pequenas funções geradoras focadas, sem nunca materializar toda a sequência na memória. Introduzido no PHP 7.0, yield from é a forma padrão de achatar geradores aninhados.
Este capítulo aborda a sintaxe básica, como as chaves são tratadas, como capturar o valor de retorno de um gerador delegado e quando a delegação é a ferramenta certa.
Sintaxe básica
yield from aparece dentro de uma função geradora e é seguido por qualquer iterável:
yield from $iterable; // generator, array, or TraversableAqui está um exemplo mínimo que combina dois geradores em um único fluxo:
<?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() não produz nenhum valor próprio — ele delega inteiramente para os outros dois geradores. Chamá-lo retorna os valores de myGenerator() primeiro, depois os de myOtherGenerator(), então o foreach imprime:
Hello World !Você pode misturar livremente delegação com instruções yield regulares na mesma função:
<?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 5Delegando para arrays e outros iteráveis
A fonte após yield from não precisa ser um gerador. Qualquer array ou Traversable funciona, o que é útil para achatar sequências fixas e lazy juntas:
<?php
function items()
{
yield from ['apple', 'banana']; // an array
yield from ['cherry'];
}
foreach (items() as $item) {
echo $item . "\n";
}
// Output:
// apple
// banana
// cherryComo as chaves são tratadas
yield from preserva as chaves do iterável interno, não apenas os valores. Este é o equívoco mais comum: as chaves não são renumeradas, então duas fontes delegadas podem produzir chaves 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 => 3Como as chaves são mantidas como estão, não confie em uma sequência contínua 0, 1, 2, … ao delegar para fontes com chaves inteiras — colete os valores em um array com iterator_to_array($gen, false) se precisar reindexá-los.
Capturando o valor de retorno do gerador interno
Um gerador delegado pode return um valor final (separado dos valores que ele retorna com yield). A expressão yield from avalia para esse valor de retorno, que você pode atribuir a uma variável:
<?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: 3Observe que o valor de return do gerador interno é capturado pelo yield from — ele não é encaminhado para o loop foreach. Apenas os valores retornados com yield (1, 2, 3) chegam ao consumidor.
Quando usar yield from
Use yield from quando quiser:
- Compor geradores — construir um pipeline a partir de pequenas funções geradoras de propósito único, em vez de uma função grande.
- Achatar estruturas aninhadas — percorrer recursivamente árvores ou arrays aninhados e emitir um único fluxo plano de valores.
- Manter eficiência de memória — os valores fluem de forma lazy, um por vez, então você nunca mantém a sequência completa na memória.
Comparado com o re-yielding manual (foreach ($inner as $v) { yield $v; }), yield from é mais curto, preserva chaves automaticamente e encaminha o valor de retorno do gerador interno — portanto, prefira-o sempre que estiver delegando para outro iterável.
Tópicos relacionados
- yield — a base dos geradores no PHP.
- loop foreach — como os valores do gerador são consumidos.
- Funções PHP e return — os blocos de construção por trás das funções geradoras.