Matthias
Matthias

Reputation: 2775

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

I know that this can be super easily archieved without generators, however I want to understand generators better. Therefore please don't suggest using something else.


I've got a class that generates filenames for screenshots (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);
        }
    }
}

Now my question is: can I use such a generator in any other context than a foreach loop? e.g.

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

for me this always returns null, and if I debug, it never enters the generator method. Also the PHP docs don't really mention this.

So my question is: is there a documented way to use a generator in a different context than a for-loop?

Upvotes: 4

Views: 1793

Answers (2)

ToolmakerSteve
ToolmakerSteve

Reputation: 21321

Here is a complete code snippet to go with Dark Duck's answer. 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();
}

The above is roughly equivalent to:

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

or

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

Upvotes: 0

DARK_DUCK
DARK_DUCK

Reputation: 1777

There is a documented way to do this. In fact Generator does implement the iterator interface as you can see it on this page.

In fact the foreach keyword only work on iterators. So if you can use foreach on a generator you must be able to call next

Here is a sample code using next instead of foreach :

<?php

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

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

?>

Upvotes: 2

Related Questions