稀里糊涂系列之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中使用协程实现多任务调度》,向大佬学习,收益颇多。

相关文章
相关标签/搜索