Edit report at https://bugs.php.net/bug.php?id=51460&edit=1

 ID:                 51460
 Updated by:         ni...@php.net
 Reported by:        a at b dot c dot de
 Summary:            yield syntax construct
-Status:             Assigned
+Status:             Closed
 Type:               Feature/Change Request
 Package:            *Programming Data Structures
 Operating System:   Irrelevant
 PHP Version:        5.3.2
 Assigned To:        nikic
 Block user comment: N
 Private report:     N

 New Comment:

This is now implemented. For more info see https://wiki.php.net/rfc/generators.


Previous Comments:
------------------------------------------------------------------------
[2010-04-02 01:37:18] a at b dot c dot de

Description:
------------
I draw your attention to the "yield" construct as used in Python, (recent) 
JavaScript, and C#. This would be I think a nice way of creating Iterators for 
traversing complex objects.

A method that uses "yield" can be replaced by one that declares an instance of 
a custom implementation of Iterator that takes $this and the method's arguments 
in its constructor, and cranks through a state machine on each call of next(). 
(Microsoft's C# compiler handles it in essentially this way, but has a much 
harder time of it because of things like multithreading and explicit resource 
disposal.)

To some extent this can be done by hand now (I've done some work on a 
preprocessing script that automates this) but in the absence of inner classes 
(which is what this Iterator ought to be) - hint, hint - it plays havoc with 
visibility attributes.

Expected result:
----------------
/*
Example method that produces an inorder traversal of a binary tree.
foreach($btree->traverse_inorder() as $node)
{
    do_something_with($node);
}
*/
public function traverse_inorder()
{
        foreach($this->left->traverse_inorder() as $child)
        {
                yield $child;
        }
        yield $this;
        foreach($this->right->traverse_inorder() as $child)
        {
                yield $child;
        }
}


Actual result:
--------------
/*
The state machine that implements the body of the test script's function 
(identifies if the end of the traversal has been reached, and obtains the next 
value to return if not)
*/
do
{
        switch($this->_state)
        {
        case -1:
                return false;
        case 0:
                // the object being traversed needs "left" made public
                $this->_t1 = $this->_this->left->traverse_inorder();
                reset($this->_t1);
                $this->_state = 1;
        case 1:
                if(!($e = each($this->_t1)))
                {
                        $this->_t1 = null;
                        $this->_state = 2;
                        continue;
                }
                $this->_value = $e['value'];
                return true;
        case 2:
                $this->_value = $this->_this;
                $this->_state = 3;
                return true;
        case 3:
                // the object being traversed needs "right" made public
                $this->_t2 = $this->_this->right->traverse_inorder();
                reset($this->_t2);
                $this->_state = 4;
        case 4:
                if(!($e = each($this->_t2)))
                {
                        $this->_t2 = null;
                        $this->_state = -1;
                        return false;
                }
                $this->_value = $e['value'];
                return true;
        }
} while(false);



------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=51460&edit=1

Reply via email to