稀裏糊塗系列之yield前瞻

前言

上一次發了一篇關於閉包中間件的文章,只是略微提到一點皮毛(也只理解到了那麼點皮毛)。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
複製代碼

讓咱們來捋捋這段代碼,看看到底發生了什麼。指針

  • First,yield會實例化一個Generator對象(也就是[1]),而且自動調用其rewind()方法
  • Second,把生成的Generator實例化賦值給$res[2]
  • Thirty,經過current()獲取當前Generator中存儲(內部指針的位置)的值'hello'並輸出([3]
  • Fouth,經過send()方法,使得程序回到了[1]位置,而且把send()方法的參數賦值給$y並輸出([5]

再次

多來幾個yieldcode

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中使用協程實現多任務調度》,向大佬學習,收益頗多。

相關文章
相關標籤/搜索