我希望逐步编写示例代码,说明如何将任务分离在生成器中,并将它们移动到2个或更多的生成器中,以实现它们之间的协作多任务处理。您可以在这里找到所有关于此的测试内容。
生成器在某种程度上是有逻辑性的,但我被一个无法解释为什么会这样工作的单一步骤所困扰:
生成器:
意外成功的测试:
生成器在某种程度上是有逻辑性的,但我被一个无法解释为什么会这样工作的单一步骤所困扰:
生成器:
$spy = new Object();
$spy->tasks = array();
$createGenerator = function ($i1) use ($spy) {
yield; //(* -> task 1)
$spy->tasks[] = $i1;
yield($i1); //(task 1 -> *)
$i1 = yield; //(* -> task 2)
//task 2
$i2 = $i1 + 1;
$spy->tasks[] = $i2;
yield($i2); //(task 2 -> *)
$i2 = yield; //(* -> task 3)
$i3 = $i2 + 1;
$spy->tasks[] = $i3;
yield($i3); //(task 3 -> *)
$i3 = yield; //(* -> task 4)
$i4 = $i3 + 1;
$spy->tasks[] = $i4;
yield($i4); //(task 4 -> *)
$i4 = yield; //(* -> task 5)
$i5 = $i4 + 1;
$spy->tasks[] = $i5;
yield($i5); //(task 5 -> *)
};
我期望测试能够成功,但是失败了:
/** @var Generator $generator */
$generator = $createGenerator(1);
$i1 = $generator->send(null);
$generator->send($i1);
$i2 = $generator->send(null);
$generator->send($i2);
$i3 = $generator->send(null);
$generator->send($i3);
$i4 = $generator->send(null);
$generator->send($i4);
$i5 = $generator->send(null);
$this->assertSame($spy->tasks, array(1, 2, 3, 4, 5));
$this->assertSame(array($i1, $i2, $i3, $i4, $i5), array(1, 2, 3, 4, 5));
意外成功的测试:
/** @var Generator $generator */
$generator = $createGenerator(1);
$i1 = $generator->send(null);
$generator->send(null); //blank sends needed to skip the yield-yield gaps
$i2 = $generator->send($i1);
$generator->send(null);
$i3 = $generator->send($i2);
$generator->send(null);
$i4 = $generator->send($i3);
$generator->send(null);
$i5 = $generator->send($i4);
$this->assertSame($spy->tasks, array(1, 2, 3, 4, 5));
$this->assertSame(array($i1, $i2, $i3, $i4, $i5), array(1, 2, 3, 4, 5));
你能解释一下使用双 yield
时生成器的奇怪行为吗?
结论:
send()
总是运行从一个 yield
的输入到下一个 yield
的输出的代码。因此,通过使用 send()
运行 Generator
,它总是以一个输入开始,这就是为什么你不能使用 send()
获取第一个 yield
的输出,并且在最后一个 send()
之前总是会得到一个 null
返回值,这时候 Generator
进入无效状态...不幸的是,PHP手册缺乏这方面的信息...
send()
和yield
结合使用的一般规则! - inf3rnoyield
和一个send(null)
,这样也可以工作...重要的是要理解,send()
运行从yield
的输入到下一个yield
的输出的代码,并且它始终以一个输入开始,这就是为什么你不能使用send()
获取第一个yield
的输出。嗯,我想我会把这部分作为结论添加到问题中。 - inf3rno