稀里糊涂系列之yield前瞻

前言

上一次发了一篇关于闭包中间件的文章,只是略微提到一点皮毛(也只理解到了那么点皮毛)。

将技术知识放到具体的应用场景中,才能更好的理解它。恰巧我前两天在对一个统计数据脚本进行升级优化时,算是对 “闭包” 进行了一点点小的应用吧,我后续会单独发一篇文章谈谈心得。

今天,说说我学习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中使用协程实现多任务调度》,向大佬学习,收益颇多。

猜你喜欢

转载自juejin.im/post/5c076c0be51d4573802aad8c