Skip to content

Instantly share code, notes, and snippets.

@Jamlee
Created July 9, 2021 08:16
Show Gist options
  • Save Jamlee/0d977b90594eacbd4e6777d41a780a78 to your computer and use it in GitHub Desktop.
Save Jamlee/0d977b90594eacbd4e6777d41a780a78 to your computer and use it in GitHub Desktop.
PHP 中 yield:嵌套展平 yield 表达式
function stackedCoroutine(\Generator $gen)
{
$stack = new \SplStack;
$exception = null;
for (;;) {
try {
if ($exception) {
$gen->throw($exception);
$exception = null;
continue;
}
// 执行一次 yield
$value = $gen->current();
if ($value instanceof \Generator) {
// 压入当前的 $gen, 先把嵌套的 $gen 执行
$stack->push($gen);
$gen = $value;
continue;
}
// 当前的 gen 函数是否执行完毕了
$isReturnValue = $value instanceof CoroutineReturnValue;
if (!$gen->valid() || $isReturnValue) {
if ($stack->isEmpty()) {// 堆栈已空
return;
}
// 找到之前的 gen
$gen = $stack->pop();
// 把值发送到上个gen函数的yield表达式上
$gen->send($isReturnValue ? $value->getValue() : NULL);
continue;
}
// 当前的gen还没有执行完毕
try {
// yield 一对 key value
// https://www.php.net/manual/en/class.generator.php
$sendValue = (yield $gen->key() => $value);
} catch (\Exception $e) {
$gen->throw($e);
continue;
}
// 发送收敛后的值
$gen->send($sendValue);
} catch (\Exception $e) {
if ($stack->isEmpty()) {
throw $e;
}
$gen = $stack->pop();
$exception = $e;
}
}
}
// 函数参数嵌套yield
function add($a, $b) {
echo "a:$a b:$b\n";
return $a + $b;
}
function yield_value() {
return 10;
}
function testFunc() {
$res = yield add(yield yield_value(), 20);
}
$t = stackedCoroutine(testFunc());
echo "第一次:" . $t->current() . "\n";
$t->send($t->current());
echo "第二次:" . $t->current() . "\n";
$t->send();
if (!$t->valid()) {
echo "generator is closed\n";
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment