这是一个简单的JavaScript生成器(来自:http://blog.carbonfive.com/2013/12/01/hanging-up-on-callbacks-generators-in-ecmascript-6/)
function* powGenerator() {
var result = Math.pow(yield "a", yield "b");
return result;
}
var g = powGenerator();
console.log(g.next().value); // "a", from the first yield
console.log(g.next(10).value); // "b", from the second
console.log(g.next(2).value); // 100, the result
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用类似于PHP的模型,但这有点令人头疼.
<?php
function powGenerator() {
return pow((yield 'a'), (yield 'b'));
}
Run Code Online (Sandbox Code Playgroud)
在我走得更远之前,我在PHP中遇到了这个错误
致命错误:生成器无法使用"返回"返回值
好吧,也许我会用另一个产量来获得最终价值?...
<?php
function powGenerator() {
yield pow((yield 'a'), (yield 'b'));
}
$g = powGenerator(); //=> Generator {#180}
echo $g->send(10); //=> "b"
echo $g->send(2); //=> 100
Run Code Online (Sandbox Code Playgroud)
好的,所以我恢复了价值,但这里有两个主要问题
我"a"去哪儿了?- 请注意,在JS示例中,我能够访问"a"和生成的"b"值以及100最终结果.
发电机还没有完成!- 我需要send额外的时间来完成发电机
$g->valid(); //=> true
$g->send('?'); //=> null
$g->valid(); //=> false
Run Code Online (Sandbox Code Playgroud)来自PHP Generator :: send
public mixed Generator::send ( mixed $value )作为当前
yield表达式的结果将给定值发送到生成器并继续执行生成器.如果在
yield调用此方法时生成器不在表达式中,则yield在发送值之前首先让它前进到第一个表达式.因此,没有必要使用Generator :: next()调用"启动"PHP生成器(就像在Python中完成一样).
强调"因此没有必要"使用Generator::next()".好的,但这究竟意味着什么?我没有像JavaScript示例那样"填充"它,但是第一个产生的值也被吞噬了.
任何人都可以解释你是如何在没有使用的情况下逐步完成发电机的foreach?
use*_*918 13
第一个产生的价值没有被吞噬,你只是从来没有看过它.
$g = powGenerator();
echo $g->current(); //a
Run Code Online (Sandbox Code Playgroud)
然后,您将两次发送值并恢复执行,之后$g->valid()是true因为您没有在第三次之后恢复yield- 生成器未完成且可能还有更多要做的事情.考虑:
function powGenerator() {
yield pow((yield 'a'), (yield 'b'));
echo "Okay, finishing here now!\n";
}
$g = powGenerator();
echo $g->current(), "\n"; //a
echo $g->send(10), "\n"; //b
echo $g->send(2), "\n"; //100
$g->next(); // Resumes execution of the generator,
// which prints its own message and completes.
var_dump($g->valid()); //false
Run Code Online (Sandbox Code Playgroud)
这个'输出:
a
b
100
Okay, finishing here now!
bool(false)
Run Code Online (Sandbox Code Playgroud)
现在在PHP 7中,您可以 从生成器返回.
function powGenerator() {
return pow((yield 'a'), (yield 'b'));
echo "This will never print.";
}
$g = powGenerator();
echo $g->current(), "\n"; //a
echo $g->send(10), "\n"; //b
echo $g->send(2), "\n"; // Prints just the newline, you're moving on
// to a return which you must get explicitly.
var_dump($g->valid()); // Generator complete, you're free to get the return.
echo $g->getReturn(), "\n";
Run Code Online (Sandbox Code Playgroud)
哪个输出:
a
b
bool(false)
100
Run Code Online (Sandbox Code Playgroud)
至于步进它们没有foreach- Generator实现Iterator,所以它有适当的方法来处理它:current,key,next,rewind和valid.随着该警告rewind,如果你把它在一个已经开始的发电机会抛出异常.
这样做的一个例子也演示了PHP 7的新生成器委派:
function letterGenerator() {
yield from range('a', 'z');
}
$g = letterGenerator();
while ($g->valid()) {
echo $g->current();
$g->next();
}
Run Code Online (Sandbox Code Playgroud)
输出:
abcdefghijklmnopqrstuvwxyz
Run Code Online (Sandbox Code Playgroud)