I have a method which takes a generator plus some additional parameters and yields a new generator:
function merge(\Generator $carry, array $additional)
{
foreach ( $carry as $item ) {
yield $item;
}
foreach ( $additional as $item ) {
yield $item;
}
}
The usual use case for this function is similar to this:
function source()
{
for ( $i = 0; $i < 3; $i++ ) {
yield $i;
}
}
foreach ( merge(source(), [4, 5]) as $item ) {
var_dump($item);
}
But the problem is that sometimes I need to pass empty source to the merge
method. Ideally I would like to be able to do something like this:
merge(\Generator::getEmpty(), [4, 5]);
Which is exactly how I would do in C# (there is a IEnumerable<T>.Empty
property). But I don't see any kind of empty
generator in the manual.
I've managed to work around this (for now) by using this function:
function sourceEmpty()
{
if ( false ) {
yield;
}
}
And this works. The code:
foreach ( merge(sourceEmpty(), [4, 5]) as $item ) {
var_dump($item);
}
correctly outputs:
int(4)
int(5)
But this is obviously not an ideal solution. What would be the proper way of passing an empty generator to the merge
method?
I've found the solution:
Since
\Generator
extends\Iterator
I can just change the method signature to this:This is input covariance thus it would break backward compatibility, but only if someone did extend the
merge
method. Any invocations will still work.Now I can invoke the method with PHP's native
EmtpyIterator
:And the usual generator also works:
Bit late, but needed an empty generator myself, and realized creating one is actually quite easy...
Don't know if that's better than using the
EmptyIterator
, but this way you get exactly the same type as non-empty generators at least.As explained in the official docs, you can create an in-line
Generator
instance, by usingyield
in an expression:That should work, but when I tried using that, I got a fatal error (
yield
expression can only be used in a function). Usingnull
didn't help either:So I guess you're stuck with the
sourceEmpty
function... it was the only thing I found that works... note that it will create anull
value in the array you're iterating.All the code was tested on PHP 5.5.9, BTW
The best fix I can come up with (seeing as compatibility is an issue) would be to make both arguments optional:
This way, existing code won't brake, and instead of constructing an empty generator, passing
null
will work just fine, too.