上一次發了一篇關於閉包中間件的文章,只是略微提到一點皮毛(也只理解到了那麼點皮毛)。php
將技術知識放到具體的應用場景中,才能更好的理解它。恰巧我前兩天在對一個統計數據腳本進行升級優化時,算是對 「閉包」 進行了一點點小的應用吧,我後續會單獨發一篇文章談談心得。html
今天,說說我學習yield
的一些小感覺吧。 網上關於yield
的示例最多的,就是一個xrange()
的實現吧。都爛大街了,我就不按這個套路來了......shell
來段小白代碼閉包
function fini() {
$x = 'hello';
yield $x;
}
$res = fini();
echo $res->current(); // hello
複製代碼
給小白觀衆說明一下吧。yield
關鍵字在這裏和return
的做用有點像。函數
區別呢,就是它返回的是一個Generator
對象的實例,我這裏調用的current()
就是它的方法之一。 也就是說,只要一個函數中有yield
,那麼調用這個函數就會返回Generator
。列一下官網手冊:學習
Generator implements Iterator {
/* 方法 */
public mixed current ( void )
public mixed key ( void )
public void next ( void )
public void rewind ( void )
public mixed send ( mixed $value )
public void throw ( Exception $exception )
public bool valid ( void )
public void __wakeup ( void )
}
複製代碼
來段高級小白的代碼優化
function fini() {
$x = 'hello';
$y = (yield $x); // [1]
echo $y; // [5]
}
$res = fini(); // [2]
echo $res->current(); // [3]
$res->send(' world'); // [4]
複製代碼
接下就是yield
神奇的地方了,他會輸出:spa
hello world
複製代碼
讓咱們來捋捋這段代碼,看看到底發生了什麼。指針
yield
會實例化一個Generator
對象(也就是[1]
),而且自動調用其rewind()
方法Generator
實例化賦值給$res
([2]
)current()
獲取當前Generator
中存儲(內部指針的位置)的值'hello'
並輸出([3]
)send()
方法,使得程序回到了[1]
位置,而且把send()
方法的參數賦值給$y
並輸出([5]
)多來幾個yield
code
function fini() {
$x = 'hello';
$y = (yield $x);
echo $y;
yield ' world';
}
$res = fini();
echo $res->current();
$wes = $res->send(' big');
echo $wes;
複製代碼
最終輸出結果:
hello big wolrd
複製代碼
我以爲,yield
就是一把 「切腸刀」,把函數這根 「香腸」 切成n截,而後依次放到Generator
這個 「飯盒」,而後你須要 「吃」 的時候,拿出一截來,可是 「吃」 的時候只能按照放好的次序來 「吃」。
比喻可能有不當的地方,作拋磚引玉,但願大佬來斧正。
最最後,安利一波鳥哥的《在PHP中使用協程實現多任務調度》,向大佬學習,收益頗多。