2016-06-14 39 views
4

通常我不会对语言结构感到困惑,但我无法对这里发生的事情做出正面或反面的评论。发生器::发送工作如何?

<?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); 
} 

打印:

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 

所以我的循环的每2迭代被跳过,我得到NULL$ans周期性。什么??

我想$ans会收到$gen->send的结果,如果我没有在未来yield之前发送任何东西,然后$ans将是空的,但我总是送些什么东西在每次迭代,那么什么是怎么回事?

+0

尝试颠倒顺序。我认为(不知道),你需要发送它之前,它可以用在生成器中的回声。 – apokryfos

+0

@apokryfos颠倒现在的顺序?在定义之前,我无法打印'$ ans'。也许'foreach'正在搞乱它...... – mpen

+0

我在说'$ gen-> send($ x); echo“loop $ x \ n”;'并比较差异而不是当前的echo - > send'组合 – apokryfos

回答

1

我认为'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); 
} 

打印我所期望的:

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 

事情变得怪异再次但如果你不是每一次循环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); 
} 

打印:

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 

我觉得这里发生的事情是send导致action迭代两次迭代每个while迭代。如果我们删除两个sends(),那么我们会陷入无限循环。所以... send()正在推进迭代器,而current()没有。我想这也解释了foreach循环会发生什么 - foreachsend()都推进了迭代器,这就是为什么每个其他结果都被跳过的原因!