1.2.1126. Should Yield With Key¶
iterator_to_array() overwrite generated values with the same key.
PHP generators are based on the yield keyword. They also delegate some generating to other methods, with yield from.
When delegating, yield from uses the keys that are generated with yield, and otherwise, it uses auto-generated index, starting with 0.
The trap is that each yield from reset the index generation and start again with 0. Coupled with iterator_to_array(), this means that the final generated array may lack some values, while a foreach() loop would yield all of them.
Thanks to Holger Woltersdorf for pointing this.
<?php
function g1() : Generator {
for ( $i = 0; $i < 4; $i++ ) { yield $i; }
}
function g2() : Generator {
for ( $i = 5; $i < 10; $i++ ) { yield $i; }
}
function aggregator() : Generator {
yield from g1();
yield from g2();
}
print_r(iterator_to_array());
/*
Array
(
[0] => 6
[1] => 7
[2] => 8
[3] => 9
[4] => 4 // Note that 4 and 5 still appears
[5] => 5 // They are not overwritten by the second yield
)
*/
foreach ( aggregator() as $i ) {
print $i.PHP_EOL;
}
/*
0 // Foreach has no overlap and yield it all.
1
2
3
4
5
6
7
8
9
*/
?>
See also Generator syntax and Yielding values with keys.
1.2.1126.1. Connex PHP features¶
1.2.1126.1.1. Suggestions¶
Use iterator_to_array() on each generator separately, and use array_merge() to merge all the arrays.
Always yield with distinct keys
Avoid iterator_to_array() and use foreach()
1.2.1126.1.2. Specs¶
Short name |
Functions/ShouldYieldWithKey |
Rulesets |
|
Exakat since |
1.5.2 |
PHP Version |
All |
Severity |
Major |
Time To Fix |
Slow (1 hour) |
Precision |
Very high |
Available in |