Geradores recursivos em PHP

Introdução

Desde a versão 5.5 no PHP há uma coisa tão boa quantogeradores. Eu não vou repetir a página de manual oficial, mas eles são ótimos para uma curta definição de iteradores. A amostra mais conhecida é:

function xrange($from, $till, $step)
{
   if ($from>$till || $step<=0)
   {
      throw new InvalidArgumentException('Invalid range initializers');
   }

   for ($i = $from; $i < $till; $i += $step)
   {
      yield $i;
   }
}

//...

foreach (xrange(2, 13, 3) as $i)
{
   echo($i.PHP_EOL); // 2,5,8,11
}

e gerador na verdade não é uma função, mas uma instância de uma classe concreta:

get_class(xrange(1, 10, 1)); // Generator


O problema

Feito com coisas RTM, agora passando para a minha pergunta. Imagine que nós queremos criar um gerador deNúmeros de Fibonacci. Normalmente, para obtê-los, podemos usar uma função simples:

function fibonacci($n)
{
   if(!is_int($n) || $n<0)
   {
      throw new InvalidArgumentException('Invalid sequence limit');
   }
   return $n < 2 ? $n : fibonacci($n-1) + fibonacci($n-2);
}

var_dump(fibonacci(6)); // 8

Vamos transformar isso em algo, isso valeseqüência e não é apenas o último membro:

function fibonacci($n)
{
   if (!is_int($n) || $n<0)
   {
      throw new InvalidArgumentException('Invalid sequence limit');
   }
   if ($n<2)
   {
      return range(0, $n);
   }
   $n1 = fibonacci($n-1);
   $n2 = fibonacci($n-2);
   return array_merge($n1, [array_pop($n1)+array_pop($n2)]);
}

//...

foreach (fibonacci(6) as $i)
{
   echo($i.PHP_EOL); // 0,1,1,2,3,5,8
}

Temos agora uma função que retorna array com sequência completa


A questão

Finalmente, a parte da questão: como posso transformar minha últimafibonacci função por isso vaiprodução meus valores, não os segurando em uma matriz? Minhas$n pode ser grande, então eu quero usar os benefícios dos geradores, como emxrange amostra. O pseudo-código será:

function fibonacci($n)
{
   if (!is_int($n) || $n<0)
   {
      throw new InvalidArgumentException('Invalid sequence limit');
   }

   if ($n<2)
   {
      yield $n;
   }

   yield fibonacci($n-2) + fibonacci($n-1);
}

Mas isso, obviamente, é uma porcaria, já que não podemos lidar com isso dessa maneira, porque a recursão causará objeto de classeGenerator e nãoint valor.

Bônus: obter a seqüência de fibonacci é apenas uma amostra para uma pergunta mais geral: como usar geradores com recursão em um caso comum? Claro, eu posso usar o padrãoIterador para isso ou reescrever minha função para evitar a recursão. Mas eu quero conseguir isso com geradores. Isso é possível? Isso vale esforços para usar isso dessa maneira?

questionAnswers(8)

yourAnswerToTheQuestion