如何产生空发电机?

Mac*_* Sz 12 php yield language-design language-details

我有一个方法,它采用一个生成器加上一些额外的参数,并产生一个新的生成器:

function merge(\Generator $carry, array $additional)
{
    foreach ( $carry as $item ) {
        yield $item;
    }
    foreach ( $additional as $item ) {
        yield $item;
    }
}
Run Code Online (Sandbox Code Playgroud)

此函数的常用用例与此类似:

function source()
{
    for ( $i = 0; $i < 3; $i++ ) {
        yield $i;
    }
}

foreach ( merge(source(), [4, 5]) as $item ) {
    var_dump($item);
}
Run Code Online (Sandbox Code Playgroud)

但问题是有时我需要将空源传递给merge方法.理想情况下,我希望能够做到这样的事情:

merge(\Generator::getEmpty(), [4, 5]);
Run Code Online (Sandbox Code Playgroud)

这正是我在C#中所做的事情(有一个IEnumerable<T>.Empty属性).但我手册中没有看到任何类型的empty发电机.

我已经设法使用此函数解决此问题(现在):

function sourceEmpty()
{
    if ( false ) {
        yield;
    }
}
Run Code Online (Sandbox Code Playgroud)

这很有效.代码:

foreach ( merge(sourceEmpty(), [4, 5]) as $item ) {
    var_dump($item);
}
Run Code Online (Sandbox Code Playgroud)

正确输出:

int(4)
int(5)
Run Code Online (Sandbox Code Playgroud)

但这显然不是一个理想的解决方案.将空生成器传递给merge方法的正确方法是什么?

Svi*_*ish 15

有点迟了,但自己需要一个空的发电机,并意识到创建一个实际上很容易......

function empty_generator(): Generator
{
    yield from [];
}
Run Code Online (Sandbox Code Playgroud)

不知道这是否比使用它更好EmptyIterator,但这样你至少可以获得与非空生成器完全相同的类型.


hak*_*kre 6

为了完整起见,也许是迄今为止最简单的答案:

function generator() {
    return; yield;
}
Run Code Online (Sandbox Code Playgroud)

我只是想知道同样的问题,并记得文档中的早期描述(直到今天至少在语义上应该如此),生成器函数是带有关键字的任何函数yield

现在,当函数在产生之前返回时,生成器应该为空。

就是这样。

3v4l.org 上的示例: https: //3v4l.org/iqaIY


Mac*_* Sz 3

我找到了解决方案:

由于\Generator扩展\Iterator我可以将方法签名更改为:

function merge(\Iterator $carry, array $additional) 
{
    // ...
Run Code Online (Sandbox Code Playgroud)

这是输入协方差,因此它破坏向后兼容性,但前提是有人扩展了该merge方法。任何调用仍然有效。

现在我可以使用 PHP 的本机调用该方法EmptyIterator

merge(new \EmptyIterator, [4, 5]);
Run Code Online (Sandbox Code Playgroud)

通常的生成器也可以工作:

merge(source(), [4, 5])
Run Code Online (Sandbox Code Playgroud)