【发布时间】:2014-05-30 12:21:28
【问题描述】:
我想逐步编写示例代码,如何在生成器中分离任务并将它们移动到 2 个或更多生成器中,以实现它们之间的协作多任务处理。你可以找到我关于这个here的所有测试。
生成器在某种程度上是合乎逻辑的,但我被一个步骤卡住了,我无法解释为什么它会这样工作:
生成器:
$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));
你能用 double yield 解释一下生成器的这种奇怪行为吗?
结论:
send() 始终将代码从yield 的输入运行到下一个yield 的输出。所以通过运行Generator 和send(),它总是以输入开始,这就是为什么你不能用send() 得到第一个yield 的输出,这就是为什么你总是得到一个null 返回值到最后一个 send(),在 Generator 进入无效状态之前...遗憾的是 PHP 手册缺少此信息...
【问题讨论】: