为什么 'yield' 不覆盖 PHP 中的键值对?
Why does 'yield' not overwrite key value pairs in PHP?
我遇到了生成器的这种奇怪行为,PHP 手册中没有描述。
我有两个 foreach 循环 - 第一个设置一些默认值,第二个覆盖它们。但是由于缺少一些 key:value 对,我无法使用 array_merge(),所以我尝试使用生成器来达到这个目的。
我发现即使 docs say:
在关联数组中 yield 键被覆盖
The syntax for yielding a key/value pair is very similar to that used to define an associative array, as shown below.
示例:
function yieldTest()
{
// those are array values (in my code - taken from data source; here static example)
$arr1 = ['a' => 1, 'b' => 2, 'c' => 3];
$arr2 = ['b' => 'B', 'd' => 'D'];
// 1st loop
foreach ($arr1 as $k => $v) {
yield $k => $v;
}
// 2nd loop
foreach ($arr2 as $k => $v) {
yield $k=>$v;
}
}
foreach(yieldTest() as $k=>$v) {
var_dump($k . ' = ' . $v) . "\n";
}
结果为
string(5) "a = 1"
string(5) "b = 2"
string(5) "c = 3"
string(5) "b = B"
string(5) "d = D"
所以密钥没有被覆盖。我期待得到以下输出:
string(5) "a = 1"
string(5) "b = B"
string(5) "c = 3"
string(5) "d = D"
这是正确的行为吗?
生成器不是关联数组。它说 "[t]he syntax 产生 key/value 对非常类似于 [..] 关联数组";它根本没有说生成器 的行为 类似于关联数组。
事实上,它不能执行相同的操作并删除重复的键,因为键不是一下子全部知道的。每个密钥都是在需要时生成的,而不是之前生成的。 foreach
遍历生成器的语法实际上是语法糖:
function foo() {
while (true) {
yield mt_rand(1, 2) => 'foo';
}
}
$foo = foo();
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
This will yield the same key many times, unpredictably. 很明显,它的行为根本不像数组。它只产生一对值,但这些值根本不是数组的一部分,因此不会进行重复数据删除。此外,生成器仅在被要求时产生下一个值,否则上述将导致无限循环。
我遇到了生成器的这种奇怪行为,PHP 手册中没有描述。
我有两个 foreach 循环 - 第一个设置一些默认值,第二个覆盖它们。但是由于缺少一些 key:value 对,我无法使用 array_merge(),所以我尝试使用生成器来达到这个目的。
我发现即使 docs say:
在关联数组中 yield 键被覆盖The syntax for yielding a key/value pair is very similar to that used to define an associative array, as shown below.
示例:
function yieldTest()
{
// those are array values (in my code - taken from data source; here static example)
$arr1 = ['a' => 1, 'b' => 2, 'c' => 3];
$arr2 = ['b' => 'B', 'd' => 'D'];
// 1st loop
foreach ($arr1 as $k => $v) {
yield $k => $v;
}
// 2nd loop
foreach ($arr2 as $k => $v) {
yield $k=>$v;
}
}
foreach(yieldTest() as $k=>$v) {
var_dump($k . ' = ' . $v) . "\n";
}
结果为
string(5) "a = 1"
string(5) "b = 2"
string(5) "c = 3"
string(5) "b = B"
string(5) "d = D"
所以密钥没有被覆盖。我期待得到以下输出:
string(5) "a = 1"
string(5) "b = B"
string(5) "c = 3"
string(5) "d = D"
这是正确的行为吗?
生成器不是关联数组。它说 "[t]he syntax 产生 key/value 对非常类似于 [..] 关联数组";它根本没有说生成器 的行为 类似于关联数组。
事实上,它不能执行相同的操作并删除重复的键,因为键不是一下子全部知道的。每个密钥都是在需要时生成的,而不是之前生成的。 foreach
遍历生成器的语法实际上是语法糖:
function foo() {
while (true) {
yield mt_rand(1, 2) => 'foo';
}
}
$foo = foo();
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
This will yield the same key many times, unpredictably. 很明显,它的行为根本不像数组。它只产生一对值,但这些值根本不是数组的一部分,因此不会进行重复数据删除。此外,生成器仅在被要求时产生下一个值,否则上述将导致无限循环。