Generadores recursivos en PHP

Introducción

Desde la versión 5.5 en PHP hay algo tan bueno comogeneradores. No repetiré la página del manual oficial, pero son excelentes para la definición corta de iteradores. La muestra más conocida es:

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
}

y el generador en realidad no es una función, sino una instancia de una clase concreta:

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


El problema

Hecho con RTM, ahora paso a mi pregunta. Imagina que queremos crear un generador deNúmeros de fibonacci. Normalmente, para obtenerlos, podemos usar una función simple:

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

Transformemos esto en algo, eso se sostiene.secuencia y no solo es el último miembro:

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
}

Ahora tenemos una función que devuelve matriz con secuencia completa


La pregunta

Por último, la parte de la pregunta: ¿Cómo puedo transformar mi últimafibonacci funciona para que lo hagarendimiento Mis valores, ¿no los mantengo en una matriz? Mi$n puede ser grande, así que quiero usar los beneficios de los generadores, como enxrange muestra. El pseudocó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);
}

Pero esto, obviamente, es una mierda ya que no podemos manejarlo de esta manera porque la recursión causará un objeto de claseGenerator y noint valor.

Prima: obtener la secuencia de fibonacci es solo una muestra para una pregunta más general: ¿cómo usar generadores con recursión en el caso común? Por supuesto, puedo usar el estándarIterador para eso o reescribir mi función para evitar la recursión. Pero quiero lograr eso con generadores. es posible? ¿Vale la pena hacer esfuerzos para usar esto de esta manera?

Respuestas a la pregunta(8)

Su respuesta a la pregunta