Created
July 9, 2021 08:16
-
-
Save Jamlee/0d977b90594eacbd4e6777d41a780a78 to your computer and use it in GitHub Desktop.
PHP 中 yield:嵌套展平 yield 表达式
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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