php 迭代器与和生成器

php有很多功能强大的接口,其中ArrayAccess 与 Iterator 的配合使用可以让对象与数组一样有着灵活的访问性。

当然,用ArrayAccess 与 Iterator 配合可以用来对付数组,但还有一个更好的办法同则SPL 提供的ArrayIterator

原因就是 :

ArrayIterator implement ArrayAccess, SeekableIterator, Countable, Searializable {}

而接下来要介绍的则是Iterator的更高一层用法。

与Iterator有关的函数先记录下

iterator_to_array() 把迭代器中的元素转换成数组

IteratorAggregate::getIterator() 调用一个外部迭代器

ArrayIterator

Iteartor_count() 等等

而php在使用Iterator接口则是迭代器模式的一种实现。在这里,其中的概念客户端(实现迭代过程)、迭代器、具体迭代器则会别对应于,foreach() , 继承于iterator接口的具体类和需要遍历的数组或集合。

而生成器,则是建立在理解迭代器的基础之上。

php中的生成器,可以叫做迭代生成器,因为它就是一个不可new的类,同时继承Iterator,且多了一个send() 与 生成器通信

它的实现则是通过yield关键字,或语句,或表达式,其工作方式则是,使用yield的结构体就是一个生成生成器类,当执行到yield

时,则中断该生成器,并存储其状态,当再次执行(foreach 或 while等循环结构) , 则会恢复其状态,并直到再次遇到yield

复制代码

function gen() {
    $ret = (yield 'yield1');
    var_dump($ret);
    $ret = (yield 'yield2');
    var_dump($ret);
}

$gen = gen();
var_dump($gen->current());    // output:string(6) "yield1" 当该生成器形成的时候
                              //rewind()就已经隐式的执行,即生成就已经到第一个yield中断了
var_dump($gen->send('ret1')); // output:string(4) "ret1"   (the first var_dump in gen)
                              // 这时,send()则做了它该做的,恢复中断,把值(ret1)传入yield,并返回yield(ret1), 直到再遇到yield ,无则返回null
                              // output:string(6) "yield2" (the var_dump of the ->send() return value)
                             // 这时执行到$ret = (yields 'yield2'); 时则中磁芯,并把yield表达式的值返回,
                              //此时为 yield2 ,若没有 后面的 ‘yield2’, 则会返回null
var_dump($gen->send('ret2')); //output:string(6) "yield2" (the var_dump of the ->send() return value)
                               // output:null
                   // 这时send()执行的时候 ,并没有下一个yield则返回的是null,而其恢复执行后在函数体内有一个var_dump(),所以会有output

其实,由上面的实例可总结出两点 ,

一是,初始化生成器时则已经到了一个yield,形成了中断,

二是,send 的执行实际上是,先next() , 再vaild() , 不能过则return null, 通过则current() ,返回,若是yield 后没有“默认”($ret = (yield 'default');),

则返回的是null,再进行中断,直至再次恢复。

理解了它是如何工作的,则出现了一个实际的问题,它有什么用呢?

生成器的高级使用出现在“在php中使用协程实现多任务调度”这一主题中,该主题偏难,而我对它的理解也只是到了简单的任务调度这一块

而更高级的内容,再慢慢了解。

  为什么它能完成任务的调度呢?关于这一点可类比操作系统中的程序中断,在那里,中断的作用则就是为了任务调度。

猜你喜欢

转载自my.oschina.net/u/3683692/blog/2253015