通常我不会对语言结构感到困惑,但我无法对这里发生的事情做出正面或反面.
<?php
function action() {
for($i=0; $i<10; ++$i) {
$ans = (yield expensive($i));
echo "action $ans\n";
}
}
function expensive($i) {
return $i*2;
}
$gen = action();
foreach($gen as $x) {
echo "loop $x\n";
$gen->send($x);
}
Run Code Online (Sandbox Code Playgroud)
打印:
loop 0
action 0
action
loop 4
action 4
action
loop 8
action 8
action
loop 12
action 12
action
loop 16
action 16
action
Run Code Online (Sandbox Code Playgroud)
所以我的循环的每2迭代被跳过,我得到NULL了$ans定期.什么??
我以为$ans会得到结果$gen->send,如果我没有在下一个之前发送任何东西yield,那么 $ans就是null,但我总是在每次迭代时发送一些东西,那么这里发生了什么?
我认为“foreach”把事情搞砸了。当 foreach 循环开始时,会创建一个迭代器,我猜它无法处理我将新事物注入生成器的事实。
这:
<?php
/**
* @return Generator
*/
function action() {
for($i=0; $i<10; ++$i) {
$ans = (yield expensive($i));
echo "action $ans\n";
}
}
function expensive($i) {
return $i*2;
}
$gen = action();
while($gen->valid()) {
$x = $gen->current();
echo "loop $x\n";
$gen->send($x);
}
Run Code Online (Sandbox Code Playgroud)
打印出我所期望的:
loop 0
action 0
loop 2
action 2
loop 4
action 4
loop 6
action 6
loop 8
action 8
loop 10
action 10
loop 12
action 12
loop 14
action 14
loop 16
action 16
loop 18
action 18
Run Code Online (Sandbox Code Playgroud)
如果send每个循环不止一次,事情就会变得奇怪:
<?php
/**
* @return Generator
*/
function action() {
for($i=0; $i<10; ++$i) {
$ans = (yield expensive($i));
echo "action $ans\n";
}
}
function expensive($i) {
echo "expensive $i\n";
return $i;
}
$gen = action();
while($gen->valid()) {
$x = $gen->current();
echo "loop $x\n";
$gen->send($x);
$gen->send($x);
}
Run Code Online (Sandbox Code Playgroud)
印刷:
expensive 0
loop 0
action 0
expensive 1
action 0
expensive 2
loop 2
action 2
expensive 3
action 2
expensive 4
loop 4
action 4
expensive 5
action 4
expensive 6
loop 6
action 6
expensive 7
action 6
expensive 8
loop 8
action 8
expensive 9
action 8
Run Code Online (Sandbox Code Playgroud)
我认为这里发生的情况是send导致action每次while迭代都要迭代两次。如果我们删除这两个,sends()那么我们就会陷入无限循环。所以...send()正在推进迭代器,而current()没有。我认为这也解释了循环中发生的情况foreach- 和foreach都send()在推进迭代器,这就是为什么其他所有结果都被跳过的原因!