PHP 5.6 生成器语法:生成器只能用在 foreach 循环中吗?

PHP 5.6 Generator Syntax: Can generators only be used in foreach loops?

我知道这可以在没有生成器的情况下非常容易地实现,但是我想更好地理解生成器。因此请不要建议使用其他东西。


我有一个 class 可以为屏幕截图生成文件名 (selenium):

class ScreenshotName
{

    private $counter = 0;

    public function screenshotNameIterator()
    {
         while(true) {
            yield sprintf("screenshot-%s-%s.png", date("Y-m-d\TH:i:s"), ++$this->counter);
        }
    }
}

现在我的问题是:我可以在 foreach 循环之外的任何其他上下文中使用这样的生成器吗?例如

(new ScreenshotName())->screenshotNameIterator()->next()

对我来说这总是 returns null,如果我调试,它永远不会进入生成器方法。 PHP 文档也没有真正提到这一点。

所以我的问题是: 是否有记录在案的方法来在与 for 循环不同的上下文中使用生成器?

有记录的方法可以做到这一点。事实上,Generator 确实实现了迭代器接口,正如您在 page.

上看到的那样

事实上 foreach 关键字只对迭代器起作用。所以如果你可以在生成器上使用 foreach 你必须能够调用 next

这是使用 next 而不是 foreach 的示例代码:

<?php

function evenNumbers() {
    for ($i = 0;; $i++) {
        yield 2*$i;
    }
}

$gen = evenNumbers();
$gen->next();
echo $gen->current();

?>

这里是一个完整的代码片段 . That is, it demonstrates how to use Iterator interface to iterate over all values. (Dark Duck's code is not complete.) Based on a comment by robert_e_lee on Iterator doc:

$gen = evenNumbers();
// If in a method that re-uses an iterator, may want the next line.
//OPTIONAL $gen->rewind();
while ($gen->valid()) {
    // This is the value:
    $value = $it->current();
    // You might or might not care about the key:
    //OPTIONAL $key = $it->key();

    // ... use $value and/or $key ...

    $it->next();
}

以上大致等同于:

foreach (evenNumbers() as $value) {
    // ... use $value ...
}

foreach (evenNumbers() as $key => $value) {
    // ... use $value and/or $key ...
}