资讯专栏INFORMATION COLUMN

PHP的yield是个什么玩意(一)

fxp / 1037人阅读

摘要:这个关键字到底返回的是什么我们简单看一下返回的是一个叫做中文名就是生成器的对象,而这个生成器是实现了接口至于接口,你们去手册上搜索吧。

其实,我并不是因为迭代或者生成器或者研究PHP手册才认识的yield,要不是协程,我到现在也不知道PHP中还有yield这么个鬼东西。人家这个东西是从PHP 5.5就开始引入了,官方名称叫做生成器。你要说为什么5.5年代的东西,现在才拿出来。我还想问你哟,PHP 5.3就有了的namespace为毛到最近这几年才开始正式投产。

那么,问题来了,这东西到底是有何用?

先来感受一个问题,给你100Kb的内存(是的,你没有看错,就是100Kb),然后让你迭代输出一个从1开始一直到10000的数组,步进为1。

愈先迭代数组,必先创造数组。

所以,脑门一拍,代码一坨如下:


一顿操作猛如虎,运行一下成绩1-5,你们感受一下:

528440bytes,约莫就是528Kb,几乎是100Kb的五倍了,妈的这日子没法过了。

毕竟你们也知道,最近内存价格确实贵,国家也在号召低碳节能减排,你多耗费5倍内存,就意味着多排放5倍的二氧化碳,就意味着要为多用的内存多花钱贡献给棒子... ...你想想,那可是棒子。

人都是被逼出来的,于是yield可以来救场了,大概代码如下,注意看操作:


运行一下,你们感受一下:

首先,我们观察一下yield_range这个函数跟普通函数不一样的地方,就是普通函数往往都是使用return来返回结果,而这个中则是yield。其次是普通函数中return只能返回一次,这个yield能返回好多次。

那么,我们来分析一波儿这个神奇的yield_range函数。这个yield关键字到底返回的是什么?我们简单看一下:


yield返回的是一个叫做Generator(中文名就是生成器)的object对象,而这个生成器是实现了Iterator接口(至于Iterator接口,你们去PHP手册上搜索吧)。所以,既然实现了Iterator接口(也正是因为如此,这个东西可以使用foreach进行迭代,明白了吧?),所以可以有如下代码:

valid() ){
  echo $generator->current().PHP_EOL;
  $generator->next();
}

运行结果如下所示:

重点来了:这个yield_range函数似乎能够记住它上一次运行到哪儿了,上一次运行的结果是什么,然后紧接着在下一次运行的时候继续从上次终止的地方继续开始。这不是普通的PHP函数可以做得到的!

我们知道,操作系统在调度进程的时候,会触发一个叫做“进程上下文切换”的概念。比如CPU从进程A调度给进程B了,那么当再次从进程B调度给进程A的时候,当初进程A运行到哪儿了、临时的数据结果是什么都是需要被还原的,不然,一切都要从头,那就要出大问题了。而,这个yield关键字,似乎在用户态(非系统内核级)就可以实现这个概念。所以说,用yield搞迭代,怕是真的很没出息的一件事,它能做的太多。

紧接着,我们需要认识一个生成器对象的一个方法,叫做send,简单看下下面这坨代码:

send( $generator->current() * 10 );

运行结果如图所示:

send方法可以修改yield的返回值,但是,你也不能想当然,比如下面这坨代码,你们以为运行结果是什么样呢?

send( $generator->current() * 10 );
}

本来以为运行结果是类似于这样的:


然而,唯物主义告诉我们:

结果是打脸的,你们感受一下:

原因是什么呢?原因是当你在外部向yield发送send的时候,会自动触发一次next,自己动手试下吧。

最近开了一个微信公众号,所有文章都在这里(手贱弄成服务号了)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/30996.html

相关文章

  • 填坑之PHPyield和协程在日子里(二)

    摘要:粗暴地说上面的过程就算是协程的基本概念。多线程和多进程都是操作系统参与的调度,而协程是用户自主实现的调度,协程的关键点实际上是用户层实现自主调度,大概有翻身农奴把歌唱的意思。 首先是,这是我第一次把公众号文章复制粘贴到sf.gg来。 其次是,很久很久之前,我挖了一个yield的一个坑,自己挖的坑自己填,不然迟早会把自己埋掉。 最后是,如果想看之前那个坑,请发送yield给文章末尾的公众...

    Scorpion 评论0 收藏0
  • generator探幽(1)--koa中间件机制浅析

    摘要:当运行到时,不会暂停,而是直接跳进函数执行函数内的代码。由于函数中没有,因此会一直执行完函数中的代码,并返回至函数中执行后面的代码。 本系列旨在通过对co,koa等库源码的研究,进而理解generator在异步编程中的重大作用(ps:所有代码请在node --harmony或者iojs环境中运行) koa中间件的形式 相信用过koa的小伙伴一定很熟悉下面这段代码 var app ...

    Jensen 评论0 收藏0
  • ES6初探

    摘要:可以直译为古怪到有魅力。里面基本上这些是被弱化了的,或者说是被隐藏起来了。而之前的的语法使得入门的门槛变高了。但是,于此同时,作为语言的独特魅力被削弱了。应该说,理解这些传统的语法对也很有意义。因为毕竟这些只是被隐藏,而不是被剔除。 这两天在看React的一些东西。接触到了ES6。谈谈一些粗浅的看法。 ES6其实是个简称。这东西学名叫做ECMAScript 2015,或者ES 2015...

    tianyu 评论0 收藏0
  • XSS全解析—初探

    摘要:持久型相当于存储型跨站脚本。这玩意儿涉及到一点和浏览器引擎解析的问题。说正事,是支持码形式的。的调用有几个概念我们先来了解一下。本来说的只用天完成的,没想到各种事儿拖了两天,。 前些时间准备面试的时候一直会遇到这个XSS,寥寥几句话好像很简单,后来看到同学的《XSS跨站脚本攻击剖析与防御》这本书,稍微翻看了一下,其中的学问还是挺多的。这系列的文章就当做读书笔记吧。 什么是XSS 听过很...

    Lucky_Boy 评论0 收藏0
  • PHP7下协程实现

    摘要:把中的初始化方法改下,因为我们在运行一个的时候,我们要分析出他包含了哪些子协程,然后将子协程用一个堆栈保存。总结这下应该明白怎么实现协程了吧建议不要使用的来实现协程,推荐使用,已经支持了协程,并附带了部分案例。 前言 相信大家都听说过『协程』这个概念吧。 但是有些同学对这个概念似懂非懂,不知道怎么实现,怎么用,用在哪,甚至有些人认为yield就是协程! 我始终相信,如果你无法准确地表达...

    young.li 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<