Re: Re: [PHP-DEV] Re: Generators in PHP

From: Date: Thu, 09 Aug 2012 03:30:35 +0000
Subject: Re: Re: [PHP-DEV] Re: Generators in PHP
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-62093@lists.php.net to get a copy of this message
On 2012-08-09 14:25, Larry Garfield wrote:
On 07/27/2012 07:23 AM, Lester Caine wrote:
Nikita - I am looking for a well reasoned argument as to why generator has to be added at all! 'Just because it can be' is not a valid argument, but perhaps you could add to the RFC the performance implication or advantage of what is being proposed. That would at least be some comparison with the current methods of doing the same thing?
Anthony had a very good writeup on generators and how they compare to iterators last week: http://blog.ircmaxell.com/2012/07/what-generators-can-do-for-you.html I think that does a good job of laying out the case for generators as "low-effort iterators". I for one am lazy, and would much prefer writing:
<?php function append_iterator($first, $second) {
    foreach($first as $i)
    {
        yield $i;
    }
    foreach($second as $i)
    {
        yield $i;
    }
} ?> to <?php function append_iterator($first, $second) {
    if(is_object($first) && !($first instanceof Iterator))
    {
        $first = (array)$first;
    }
    if(is_array($first))
    {
        $first = new ArrayIterator($first);
    }
    if(is_object($second) && !($second instanceof Iterator))
    {
        $second = (array)$second;
    }
    if(is_array($second))
    {
        $second = new ArrayIterator($second);
    }
    return new myAppendIterator($first, $second);
} class myAppendIterator implements Iterator { private $_state = 0; private $_key; private $_current; private $first, $second; public function __construct($first, $second) { $this->first = $first; $this->second = $second; } public function rewind() { $this->first->rewind(); $this->second->rewind(); $this->state = 0; } public function current() { return $this->_current; } public function key() { return $this->_key; } public function next() { switch($this->_state) { case -1: return; case 0: $this->first->rewind(); $this->_state = 1; case 1: if($this->first->valid()) { $this->_current = $this->first->current(); $this->_key = $this->first->key(); $this->first->next(); return; } else { $this->second->rewind(); $this->_state = 2; } case 2: if($this->second->valid()) { $this->_current = $this->second->current(); $this->_key = $this->second->key(); $this->second->next(); return; } else { $this->_state = -1; return; } } } public function valid() { return $this->_state != -1; } } ?>
One question, though: It looks based on the voting like finally {} blocks are going in. So... what should happen in the following situation: function stuff() { try {
     foreach (range(1, 100) as $i) {
       yield $i;
     }
} finally {
     print "All done";
} } Does "All done" get printed once, or 101 times? Similarly: function things() { $i = 1; try {
     while (true) {
       yield $i++;
     }
} finally {
     print "All done";
} } That will run indefinitely. So will "All done" ever print, or does that finally become unreachable? My own gut expectation (the answers that would surprise me the least) would be (a) once (because the foreach is _inside_ the try block, and the catch/finally handler is hence _outside_ the loop); and (b) the finally{} is unreachable (assuming that loop doesn't manage to throw an exception!) because control flow never gets to the end of the try block.


« previous php.internals (#62093) next »