在PHP中:“收益”,“收益”,“收益自”以及在同一函数中混合收益和收益之间有什么区别?

问题描述 投票:9回答:2

returnyield之间的区别似乎很明显,直到我发现还存在yield from,并且可以将returnyield合并为一个完全相同的功能!

我对return的理解是,not之后的一切都被执行了,对吧?

但是:

function generate(): iterable {
    return [1, 2, 3];
}

foreach (generate() as $value) {
    echo $value;
}

产生:“ 123”

但以下内容:

function generate(): iterable {
    return [1, 2, 3];
    yield;
}

foreach (generate() as $value) {
    echo $value;
}

什么也不生产!这样就意味着执行了yield?

这是错误吗?

php return generator yield
2个回答
10
投票

Return

仅将唯一值返回给调用方。

Yield

[转换当前函数/方法以返回Generator,它将产生一个以上的唯一值:每次触发Generator时,它都会一次将一个值提供给调用方,通常使用[C0 ]循环。

yield + foreach

生成器除了生成值之外,还可以提供唯一的返回值。该值将不属于生成器循环的一部分,必须使用Yield方法对其进行访问。

Return + Generator::getReturn()

这可以看作是错误,但是不是。

这是两个阶段:

  1. [从代码到字节码:在此阶段,Generator::getReturn()函数被视为包含Return关键字,因此将其标记为产生Yield
  2. Execution:因为generate()恰好在yield之前,所以生成器没有机会产生任何值。但是,可以使用Generator检索return数组。

完整的注释示例:

yield

5
投票

[1, 2, 3]

包含Generator::getReturn()的任何函数都是生成器函数。

因此Generator::getReturn()是否执行无关紧要,解析器会在函数定义中的某个位置看到它并将其转换为生成器。

如果函数从不执行// Generate integers 1 and 2 function generateIntegers1And2(): Generator { yield 1; // <--+ <--+ <--+ yield 2; // <-+ <-+ <-+ } // | | | // | | | foreach (generateIntegers1And2() as $value) { // | | | var_dump($value); // Shows 1, then 2 ->* | | } // | | // | | function generateOuterYield(): Generator { // | | // Yields the generator *itself* returned by | | // generateIntegers1And2() not the actual values | | // generated by it. | | // This means we are producing here a generator | | // of generator of integers. | | yield generateIntegers1And2(); // <-+ | | } // | | | // | | | foreach (generateOuterYield() as $value) { // | | | var_dump($value); // ->* | | // The two levels of imbrication means we have | | // to loop once more to actually consume | | // generateIntegers1And2 | | foreach ($value as $val) { // | | var_dump($val); // Shows 1, then 2 ->* | } // | } // | // | // A generator can just be returned as-is: | function generateOuterReturn(): Generator { // | return generateIntegers1And2(); // | } // | // | // it doesn't change the way it is consumed | foreach (generateOuterReturn() as $value) { // | var_dump($value); // Shows 1, then 2 | } // | // | function generateOuterYieldFrom(): Generator { // | // First yield values generated by generateIntegers1And2() | yield from generateIntegers1And2(); // *<---+ // then yield integers 3 | yield 3; // <--+ // and 4 | yield 4; // <-+ } // | // | foreach (generateOuterYieldFrom() as $value) { // | var_dump($value); // Shows 1, 2, 3 and 4 ->* } function generateIntegers56AndReturn(): Generator { yield 5; // <---+ yield 6; // <--+ // | return ["five", "six"]; // <--+ | } // | | // | | $gen = generateIntegers56AndReturn(); // | | // | | // Consume the values **yielded** by | | // generateIntegers56AndReturn() | | foreach ($gen as $value) { // | | var_dump($value); // Shows 5, then 6 | ->* } // | // | // Access the value **returned** by the generator | var_dump($gen->getReturn()); // ->* function wtf(): Generator { return ["W", "T", "F", "!"]; // Without the following line, PHP would complain with a TypeError: // Return value of wtf() must be an instance of Generator, array returned. // The presence of a yield keyword anywhere inside the function makes it a Generator. // However, since we return *before* reaching any *yield*, 42 is never yielded. // This is empty generator! yield 42; } $gen = wtf(); // This foreach loop is not entered! foreach ($gen as $value) { var_dump($value); } // However, we can loop on the array *returned* by wtf(): foreach ($gen->getReturn() as $value) { echo $value; // Will print: WTF! } 语句,则生成器不产生任何值。当您尝试使用结果时,documentation返回的值将被忽略。该文档说:

注意:在PHP 5中,生成器无法返回值:这样做将导致编译错误。空的yield语句在生成器中是有效的语法,它将终止生成器。从PHP 7.0开始,生成器可以返回值,可以使用yield进行检索。

所以您可以这样做:

yield
© www.soinside.com 2019 - 2024. All rights reserved.