Language Reference >> Predefined Interfaces and Classes >> Generator

<?php
// +----------------------------------------------------------------------
// | Language Reference >> Predefined Interfaces and Classes >> Generator
// +----------------------------------------------------------------------
// | Author: alexander <[email protected]>
// +----------------------------------------------------------------------
// | Datetime: 2017-11-13 17:48
// +----------------------------------------------------------------------
// | Perfect Is Shit
// +----------------------------------------------------------------------

/**
 * Generator implements Iterator {
 *  --Methods--
 *      public mixed current ( void )
 *      public mixed getReturn ( void )
 *      public mixed key ( void )
 *      public void next ( void )
 *      public void rewind ( void )
 *      public mixed send ( mixed $value )
 *      public mixed throw ( Throwable $exception )
 *      public bool valid ( void )
 *      public void __wakeup ( void )
 *
 */

/**
 * current 返回當前產生的值
 */
function t(){
    for($i=1;$i<=10;$i++){
        yield $i;
    }
    return 100;
}
$gen = t();
//var_dump($gen->current());
var_dump($gen->getReturn());
// 輸出 int(1)

/**
 * getReturn 返回生成器函數中return值
 * 確保使用getReturn的時候生成器函數返回return值而不是yield值,否則會報錯;
 */
$gen = (function() {
    yield 1;
    yield 2;

    return 3;
})();

foreach ($gen as $val) {
    echo $val, PHP_EOL;
}

echo $gen->getReturn(), PHP_EOL;
// 輸出:
// 1
// 2
// 3

/**
 * key 返回yield值的key
 * 如果沒有key,返回0
 */
$gen = (function() {
    yield 1 => 2;
})();
var_dump($gen->key());
var_dump($gen->current());
// 輸出:
// int(1)int(2)
$gen = (function() {
    yield 1;
})();
var_dump($gen->key());
var_dump($gen->current());
// 輸出:
// int(0)int(1)

/**
 * next 生成器繼續執行
 * 生成器已經執行到末尾,不會自動next到開始
 */
$gen = (function(){
    yield 1;
    yield 2;
    yield 3;
})();
var_dump($gen->current());
$gen->next();
var_dump($gen->current());
$gen->next();
var_dump($gen->current());
$gen->next();
var_dump($gen->current());
// 輸出:
// int(1)int(2)int(3)NULL

/**
 * rewind 重置生成器
 * 如果生成器已經執行,則會拋出一個異常
 */

/**
 * send 向生成器傳入一個值
 */
function printer()
{
    while (1) {
        $string = yield;
        echo $string . PHP_EOL;
    }
}

$printer = printer();
$printer->send('Hello world!');
$printer->send('How are you?');
// 輸出:
// Hello world!
// How are you?
//

// +----------------------------------------------------------------------
/**
 * 以下是一個通過send和yield實現的雙向通信的例子,從鳥哥那裏拿來的
 * 需要注意的是:
 *      官網說法:send方法,向生成器傳入一個值,並且把這個值作爲當前執行yield的結果,並且繼續執行生成器;
 *      也就是說,send方法做了三件事情;
 *      send方法返回的值很有意思,他返回生成器繼續執行的下一個yield返回的值,注意,不是本次yield表達式返回的值,一定要注意;
 */
function gen()
{
    $ret = (yield 'yield1');
    var_dump($ret);
    $ret = (yield 'yield2');
    var_dump($ret);
}

$gen = gen();
// 這裏輸出當前生成器的值,第一個yield的值:yield1
var_dump($gen->current());
// 這裏向生成器發送ret1,並且繼續執行生成器到下一個yield,執行生成器遇到gen裏面第一個var_dump,則輸出第一個yield表達式的值,即爲send傳入的值ret1;
// 這裏的var_dump($gen->send),則爲send方法的返回值,send方法的返回值爲下一個yield表達式返回的值,即爲yield2;
// 所以這裏輸出:
//      string(4) "ret1"   (the first var_dump in gen)
//      string(6) "yield2" (the var_dump of the ->send() return value)
var_dump($gen->send('ret1'));
// 這裏向生成器發送ret2,並且繼續執行生成器,執行生成器遇到gen裏面第二個var_dump,輸出第二個yield表達式的值,即爲send傳入的值ret2;
// 由於生成器後面沒有yield表達式,所以send方法返回爲null
// 故輸出:
//      string(4) "ret2"   (again from within gen)
//      NULL               (the return value of ->send())
var_dump($gen->send('ret2'));

// 輸出:
// string(6) "yield1"
// string(4) "ret1"   (the first var_dump in gen)
// string(6) "yield2" (the var_dump of the ->send() return value)
// string(4) "ret2"   (again from within gen)
// NULL               (the return value of ->send())
// +----------------------------------------------------------------------

/**
 * throw 向生成器中拋入一個異常
 */
$gen = (function () {
    try {
        yield 1;
    } catch (Exception $e) {
        echo $e->getMessage();
    }
})();
$gen->throw(new Exception('gen throw exception'));
// 輸出:
// gen throw exception

/**
 * valid 檢查迭代器是否被關閉
 * 當前生成器中執行到最後,則爲關閉,否則爲開啓
 */
$gen = (function () {
    yield 1;
})();

var_dump($gen->valid());
$gen->next();
var_dump($gen->valid());
// 輸出:
// bool(true)bool(false)

/**
 * __wakeup 拋出一個異常以表示生成器不能被序列化;
 */
$gen = (function () {
    yield 1;
})();
var_dump($gen->__wakeup());
// 拋出異常
// Fatal error: Uncaught Exception: Unserialization of 'Generator' is not allowed in ...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章