yield 關鍵字可用來產生 Generator。
範例:
有時我們會用 range() 函式產生一個陣列,裡面元素從1~5,之後用 foreach 做其它處理。
$a = range(1,5); // $a=array(1,2,3,4,5); foreach($a as $v){ echo $v*$v; }
若使用 Generator 生成器的方式,可省去產生完整陣列的步驟,也就減少了產生完整陣列所佔用的記憶體。
// 使用 yield 自訂一個有迭代器功能的生成器 function xrange($start, $end) { for ($i = $start; $i <= $end; $i++) { yield $i; } } $a = xrange(1,5); var_dump($a); // object(Generator)#1 (0) {},$a 是 Generator 生成器物件 var_dump($a instanceof Iterator); // bool(true),$a 也實做了 Iterator 迭代器的功能 foreach($a as $v){ // $a 不需要先產生所有元素 echo $v*$v; }
可使用的方法:rewind()、current()、key()、next()、valid()
// 另一個跌代器,1~3 $b = xrange(1,3); var_dump($b->valid()); // true var_dump($b->key()); // 0 var_dump($b->current()); // 1 $b->next(); // 下一個 $b->next(); // 到最後一個 var_dump($b->valid()); // true var_dump($b->key()); // 2 var_dump($b->current()); // 3 $b->next(); // 再下一個,沒元素了 var_dump($b->valid()); // false var_dump($b->key()); // null var_dump($b->current()); // null若在過程中使用 rewind(),會出現「Uncaught exception 'Exception' with message 'Cannot rewind a generator that was already run」錯誤,因為生成器開始使用就不能用rewind,生成器rewind說明:Generator::rewind(If iteration has already begun, this will throw an exception).
傳送資料給 Generator:send()
function printer() { while (true) { $string = yield; echo $string; } } $printer = printer(); $printer->send('Hello world!'); // Hello world!
參考:
在PHP中使用协程实现多任务调度
PHP5.5或将引入Generators
PHP: Generators overview - Manual
PHP: Generator syntax - Manual
PHP: Generator::send - Manual
重温PHP手册 – 生成器
沒有留言:
張貼留言