在副引用生成器中使用“yield from”的任何替代方法?

I want to use some methods which use Generators as their return type and by-reference. However, the problem is that a method gets another method's return value, that is returned by-reference and is a Generator, and returns it by-reference. Plus, nearly all methods return a value after yielding one or more values.

Let's see in a code:

class YieldFromByReferenceTest
{
    public $data = [
        "Ubuntu",
        "CentOS",
        "Fedora"
    ];

    protected function &sampleGenerator(): \Generator
    {
        foreach ($this->data as $key => &$datum) {
            yield $key => $datum;
        }
        // This is just a sample return type
        return true;
    }

    public function &useGenerator(): \Generator
    {
        $generator = $this->sampleGenerator();

        // Return $generator?
    }
}

Firstly, yield from came in my mind. However, when I try to use it, it gives me the following error:

PHP Fatal error: Cannot use "yield from" inside a by-reference generator in ./test.php on line xx

That looks strange to me. I don't know why it does not work (as in my mind, it should work). So, my questions are:

  1. In this case, why yield from doesn't work as expected and an error is generated? Shouldn't it work?

  2. What are the alternative solutions?

Thank you!

I'm going to post two solutions (please consider replacing the following codes with the part: // Return $generator? in the code in the question), but I can't really answer my first question.

Yielding and Returning

One possible solution is to yield all values from sampleGenerator() and then return its return value:

// Please notice the &
foreach ($generator as $key => &$value) {
    yield $key => $value;
}
return $generator->getReturn();

It works perfectly, and prevents from errors, even if using nested generators or if a generator does not yield or return any values. However, in some cases, as for me, the code would become harder to read, because of using it a lot.

Returning the Generator Itself

Simply, you can return the returned generator:

return $generator;

At first glance, it looks simpler, but if you are working on some complicated pieces of code, then it becomes a bit complicated. Just keep in mind, unless you use a yield statement somewhere in the function, it returns a Generator instance, and it is not a generator function. Notwithstanding, just like what happened for me, your problem may be fixed by adding an empty yield (pay attention, it will be a generator):

return $generator;
yield;

Note: It may be obvious, but these are not always-work solutions. You should consider your own problem and then try to fix it; so, you may need both ways to get the jobs done!

Hope it helps!