1.2.1127. 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.1127.1. Connex PHP features¶
1.2.1127.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.1127.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 |