前言
上一次發了一篇關於閉包中介軟體的文章,只是略微提到一點皮毛(也只理解到了那麼點皮毛)。
將技術知識放到具體的應用場景中,才能更好的理解它。恰巧我前兩天在對一個統計資料指令碼進行升級優化時,算是對 “閉包” 進行了一點點小的應用吧,我後續會單獨發一篇文章談談心得。
今天,說說我學習yield
的一些小感受吧。
網上關於yield
的示例最多的,就是一個xrange()
的實現吧。都爛大街了,我就不按這個套路來了......
首先
來段小白程式碼
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
神奇的地方了,他會輸出:
hello world
複製程式碼
讓我們來捋捋這段程式碼,看看到底發生了什麼。
- First,
yield
會例項化一個Generator
物件(也就是[1]
),並且自動呼叫其rewind()
方法 - Second,把生成的
Generator
例項化賦值給$res
([2]
) - Thirty,通過
current()
獲取當前Generator
中儲存(內部指標的位置)的值'hello'
並輸出([3]
) - Fouth,通過
send()
方法,使得程式回到了[1]
位置,並且把send()
方法的引數賦值給$y
並輸出([5]
)
再次
多來幾個yield
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中使用協程實現多工排程》,向大佬學習,收益頗多。