Generator syntax
Generator syntax
A generator function looks just like a normal function, except that instead of returning a value, a generator yields as many values as it needs to. Any function containing yield is a generator function.
When a generator function is called, it returns an object that can be iterated over. When you iterate over that object (for instance, via a foreach loop), PHP will call the object's iteration methods each time it needs a value, then saves the state of the generator when the generator yields a value so that it can be resumed when the next value is required.
Once there are no more values to be yielded, then the generator can simply return, and the calling code continues just as if an array has run out of values.
Opmerking: > A generator can return values, which can be retrieved using .
Generator::getReturn
yield keyword
The heart of a generator function is the keyword. In its simplest form, a yield statement looks much like a return statement, except that instead of stopping execution of the function and returning, yield instead provides a value to the code looping over the generator and pauses execution of the generator function.
Voorbeeld: A simple example of yielding values
<?php
function gen_one_to_three() {
for ($i = 1; $i <= 3; $i++) {
// Note that $i is preserved between yields.
yield $i;
}
}
$generator = gen_one_to_three();
foreach ($generator as $value) {
echo "$value\n";
}
?>
1
2
3
Opmerking: > Internally, sequential integer keys will be paired with the yielded values, just as with a non-associative array.
Yielding values with keys
PHP also supports associative arrays, and generators are no different. In addition to yielding simple values, as shown above, you can also yield a key at the same time.
The syntax for yielding a key/value pair is very similar to that used to define an associative array, as shown below.
Voorbeeld: Yielding a key/value pair
<?php
/*
* The input is semi-colon separated fields, with the first
* field being an ID to use as a key.
*/
$input = <<<'EOF'
1;PHP;Likes dollar signs
2;Python;Likes whitespace
3;Ruby;Likes blocks
EOF;
function input_parser($input) {
foreach (explode("\n", $input) as $line) {
$fields = explode(';', $line);
$id = array_shift($fields);
yield $id => $fields;
}
}
foreach (input_parser($input) as $id => $fields) {
echo "$id:\n";
echo " $fields[0]\n";
echo " $fields[1]\n";
}
?>
1:
PHP
Likes dollar signs
2:
Python
Likes whitespace
3:
Ruby
Likes blocks
Yielding null values
Yield can be called without an argument to yield a null value with an automatic key.
Voorbeeld: Yielding nulls
<?php
function gen_three_nulls() {
foreach (range(1, 3) as $i) {
yield;
}
}
var_dump(iterator_to_array(gen_three_nulls()));
?>
array(3) {
[0]=>
NULL
[1]=>
NULL
[2]=>
NULL
}
Yielding by reference
Generator functions are able to yield values by reference as well as by
value. This is done in the same way as
:
by prepending an ampersand to the function name.
returning references from functions
Voorbeeld: Yielding values by reference
<?php
function &gen_reference() {
$value = 3;
while ($value > 0) {
yield $value;
}
}
/*
* Note that we can change $number within the loop, and
* because the generator is yielding references, $value
* within gen_reference() changes.
*/
foreach (gen_reference() as &$number) {
echo (--$number).'... ';
}
?>
2... 1... 0...
Generator delegation via yield from
Generator delegation allows you to yield values from another
generator, object, or
by using the keyword.
The outer generator will then yield all values from the inner generator,
object, or array until that is no longer valid, after which execution
will continue in the outer generator.
`Traversable``array`
If a generator is used with , the expression will also return any value returned by the inner generator.
Let op: > ### Storing into an array (e.g. with iterator_to_array)
does not reset the keys. It preserves the keys returned by the object, or . Thus some values may share a common key with another or , which, upon insertion into an array, will overwrite former values with that key. `Traversable``array` A common case where this matters is returning a keyed array by default, leading to possibly unexpected results. has a second parameter which can be set to false to collect all the values while ignoring the keys returned by the . `iterator_to_array``iterator_to_array``preserve_keys``Generator`**Voorbeeld: with **
<?php function inner() { yield 1; // key 0 yield 2; // key 1 yield 3; // key 2 } function gen() { yield 0; // key 0 yield from inner(); // keys 0-2 yield 4; // key 1 } // pass false as second parameter to get an array [0, 1, 2, 3, 4] var_dump(iterator_to_array(gen())); ?>array(3) { [0]=> int(1) [1]=> int(4) [2]=> int(3) }
**Voorbeeld: Basic use of **
<?php
function count_to_ten() {
yield 1;
yield 2;
yield from [3, 4];
yield from new ArrayIterator([5, 6]);
yield from seven_eight();
yield 9;
yield 10;
}
function seven_eight() {
yield 7;
yield from eight();
}
function eight() {
yield 8;
}
foreach (count_to_ten() as $num) {
echo "$num ";
}
?>
1 2 3 4 5 6 7 8 9 10
Voorbeeld: and return values
<?php
function count_to_ten() {
yield 1;
yield 2;
yield from [3, 4];
yield from new ArrayIterator([5, 6]);
yield from seven_eight();
return yield from nine_ten();
}
function seven_eight() {
yield 7;
yield from eight();
}
function eight() {
yield 8;
}
function nine_ten() {
yield 9;
return 10;
}
$gen = count_to_ten();
foreach ($gen as $num) {
echo "$num ";
}
echo $gen->getReturn();
?>
1 2 3 4 5 6 7 8 9 10