前言
上一次发了一篇关于闭包中间件的文章,只是略微提到一点皮毛(也只理解到了那么点皮毛)。
将技术知识放到具体的应用场景中,才能更好的理解它。恰巧我前两天在对一个统计数据脚本进行升级优化时,算是对 “闭包” 进行了一点点小的应用吧,我后续会单独发一篇文章谈谈心得。
今天,说说我学习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中使用协程实现多任务调度》,向大佬学习,收益颇多。