PHP yield from 生成器用法探究(二)

繼續

上次給你們講了PHP yield 的用法,今天給你們講講 yield fromphp

看到這裏來,必定是 PHP.net 看得不過癮吧,這篇文章必定把 yield from 語法給你講透徹。git

三部曲

語法

<?php
function func()
{
    yield from $expression;
}

是的,和yield同樣,這是一個生成器語法。$expression 是必須(yield 能夠爲空爲NULL),且必須是可迭代對象。shell

快速上手

小例子1

<?php
function yield_from_func()
{
    (yield from array(1, 2, 3, 4));
}

foreach (yield_from_func() as $value)
{
    echo 'value is : ' . $value . PHP_EOL;
}
  • 運行輸出
$ php ./test.php

value is : 1
value is : 2
value is : 3
value is : 4

經過以上例子,可得 yield from 能把個數組(也能夠是迭代器)一個個遍歷並送出來。express

小例子2

<?php
function yield_func()
{
    yield 1;
    yield 2;
    yield 3;
}

function yield_from_func2()
{
    (yield from yield_func());
}

$gen = yield_from_func2();
echo 'value is : ' . $gen->current() . PHP_EOL;
$gen->next();
echo 'value is : ' . $gen->current() . PHP_EOL;
$gen->next();
echo 'value is : ' . $gen->current() . PHP_EOL;
$gen->next();
  • 運行輸出
$ php ./test.php

value is : 1
value is : 2
value is : 3

小例子2裏,yield from 右側是生成器時, 調用nextcurrent 也能將生成器內的元素一個個送出。segmentfault

探個究竟

接下來咱們,上全量測試代碼。 gitee PHP Generator Yield Demo ,探究一下yield from的各類細節。數組

git clone https://gitee.com/xupaul/PHP-generator-yield-Demo.git

紙上得來終覺淺,絕知此事要躬行多線程

運行

$ php ./yieldFromTest.php

什麼是生成器?

// ./yieldFromFunctions.php
function yield_from_func1()
{
    // yield from ;            // Parse error: syntax error, unexpected ';'
}

有一行代碼,被註釋了,語法靜態檢查都不能經過。函數

20200526150915.png

上圖是生成器判斷運行結果,yield_from_func4(), 有個if判斷是否運行到 yield from, PHP 依然斷定爲生成器。測試

其實到這裏,你們一下就清楚了,是否是生成器是靜態判斷的。編碼

<?php
function yield_from_func3()
{
    yield from 'test';
}
···
echo 'eg: NO.5' . PHP_EOL;
$gen = yield_from_func3();
echo 'call yield_from_func2 current ' . PHP_EOL;
// $re = $gen->current();          // Fatal error: Uncaught Error: Can use "yield from" only with arrays and Traversables
echo PHP_EOL;
  • 運行結果:
eg: NO.5
yield_from_func4 is PHP Generator? :true
call yield_from_func2 current

yield_from_func4雖然斷定爲生成器,一執行就報錯,可得 yield from 右側必須是一個可遍歷對象。

例子8也會運行出錯。

current、next 和 send

20200526151316.png

以上截圖,例子1,和例子2,能夠看到 yield from 和 yield 的 current,獲取當前值,next 跳過, send 向生成器傳入值,這些功能和一半生成起都差很少的。

一樣,開始時跳過current,直接調用send,會丟失第一次 yield的彈出值。

yield from 接收數據

20200526155234.png

例子:6,7.中,看到截圖中例子6 get re: 打印出 $reNULLlist($re1,$re2,$re3)一樣也是NULL.

結論: yield from 左側不能收到任何值,在左側寫賦值語句不會報錯,但也沒有意義。

那麼send進入的值,去哪了呢,繼續看

yield from 嵌套

<?php
function yield_func20 ()
{
    $arr = array();
    echo 'run to function ' . __FUNCTION__ . ' line: ' . __LINE__ . PHP_EOL;
    $arr[] = yield 2;
    $arr[] = yield 'key' => 'value';
    $arr[] = yield 7 => 'cc';
    $arr[] = yield 5;
    echo 'run to function ' . __FUNCTION__ . ' line: ' . __LINE__ . ', arr re: ';
    var_export($arr);
    echo PHP_EOL;
}

20200526160130.png

例子:9,10中,咱們實現了,從生成器中取值。 同時經過 yield_func20 函數內 $arr 變量dump發現,向生成器 send 的值,會經過 yield from 傳到內部生成器的 yield 賦值語句.

20200526161612.png

例子:12,13中,發現,yield from 是能夠多層嵌套的。

yield from 的嵌套做用,是很是重要特性,在協程編碼中,熟練使用嵌套能減小函數指針,以及生成器的應用傳遞。

總結

yield from 是一個強大且不可缺乏的語法,若是隻有 yield 那麼就只是有了生成器,有了 yield from 那就有了一根強大的「針」——穿過一個個 生成器,按照call stack 把一個個生成器串了起來。 調用方法用 call_user_func(),調用 生成器用 yield from .

好,這就是 yield from 用法的探究,實戰會放到後續文章。

歡迎提問,若是有幫助請關注,收藏,做者有新的發現,乾貨,也會更新文章。

沒人比我更懂

相關文章
相關標籤/搜索