函数中的提前返回和yield

问题描述 投票:0回答:1

我不确定使用

yield
关键字时提前返回函数的正确方法是什么。

“return void”

return;
是正确的返回值吗?因为返回类型被指定为
iterable
。尽管它的工作没有任何错误,但如果类型提示为
int
,则返回 void 会导致错误。那么
iterable
类型提示是否仍接受 void return 语句的异常,尽管类型提示指示应返回
iterable
的内容?

请参阅下面的示例来澄清我的问题:

class Collection
{
    public $items;
}

class OrderedCollection extends Collection
{
    public $orderedItems;
}

class Test
{
    public function getCollectionItems(Collection $collection): iterable
    {
        if ($collection instanceof OrderedCollection) {
            yield from $collection->orderedItems;
            return; // What should I return here to early exit the function?
        }

        yield from $collection->items;
    }
}
php generator yield
1个回答
0
投票

生成器函数的返回类型应为
\Generator
或其超类型‡。


生成器函数不会“返回”它们所产生的结果,如果您想这样考虑的话,它们会“返回”一个“yielder”。我相信大部分混乱源于将生成器函数称为生成器。

更好的思考方式是生成器 function outputs a

Generator
object

所以我们有两个术语:

另一个令人困惑的方面是,我们使用 返回类型语法 来表示该函数将 输出 a

Generator
。实际上,没有任何东西可以从生成器函数中进行字面意义上的
return
编辑。生成器函数上下文中的
return;
语句更像是函数作用域的
exit;
(你们中的迂腐者最好不要在这次讨论中提及类似的
exit(1)
价值观。
🙏


我认为这个例子很好地展示了这一切:

function test(): \Generator {
    yield 'test';
    return "This text vanishes into the abyss."; // return values aren't a thing
    return; // instead, this "void" is the only return statement that makes sense
    yield 'Execution never reaches this text.';
}

$test = test(); // this is a \Generator object

foreach($test as $item) { // \Generator objects are iterable
    echo $item; // prints 'test' and nothing else
}

‡ 在您的特定情况下(将返回类型设置为

iterator
),代码工作正常,大概是因为
Generator
是某种形式的
iterator
实现。 PHP 手册和错误使用“超类型”一词来描述允许的返回类型,但我想
iterator
(我认为是子类型)也适用。

通过将这个

iterator
视为更多的“可迭代”接口,可能会更清楚生成器函数的返回类型应该是什么:您可以迭代的东西,最准确地说,是一个
Generator
对象。


琐事:

  • yield
    语句本身使该函数成为生成器函数。这意味着,如果您在函数中的任何位置使用
    yield
    ,无论是否执行,该函数都将被“编译”为生成器函数。 (当然,这不包括注释中的
    // yield
    。)这意味着生成器函数不需要声明返回类型,但一如既往,这是最佳实践。
© www.soinside.com 2019 - 2024. All rights reserved.