Рекурсивные генераторы в PHP

Введение

Начиная с версии 5.5 в PHP есть такая замечательная вещь, какгенераторы, Я не буду повторять официальную страницу руководства, но они отлично подходят для краткого определения итераторов. Самый известный образец:

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
}

и генератор на самом деле не функция, а экземпляр конкретного класса:

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


Проблема

Закончено с RTM, теперь перейдем к моему вопросу. Представьте, что мы хотим создать генераторЧисла Фибоначчи, Обычно, чтобы получить их, мы можем использовать простую функцию:

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

Давайте превратим это во что-то, что держитпоследовательность&nbsp;и не только это последний член:

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
}

Теперь у нас есть функция, которая возвращает массив с полной последовательностью


Вопрос

Наконец, часть вопроса: как я могу преобразовать мою последнююfibonacci&nbsp;функция так будетУступать&nbsp;мои значения, не удерживая их в массиве? мой$n&nbsp;может быть большим, поэтому я хочу использовать преимущества генераторов, как вxrange&nbsp;образец. Псевдокод будет:

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);
}

Но это, очевидно, дерьмо, так как мы не можем справиться с этим таким образом, потому что рекурсия вызовет объект классаGenerator&nbsp;и нетint&nbsp;стоимость.

бонусПолучение последовательности Фибоначчи - это всего лишь пример для более общего вопроса: как использовать генераторы с рекурсией в общем случае? Конечно, я могу использовать стандартныеИтератор&nbsp;для этого или переписать мою функцию, чтобы избежать рекурсии. Но я хочу добиться этого с помощью генераторов. Это возможно? Стоит ли это усилий, чтобы использовать этот способ?