zephir-lang / zephir

Zephir is a compiled high-level language aimed to ease the creation of C-extensions for PHP
https://zephir-lang.com
MIT License
3.3k stars 466 forks source link

[DOC] Iterator isn't iterable internally #1081

Open MarkBaker opened 9 years ago

MarkBaker commented 9 years ago

Zephir 0.7.1b

I've created a simple iterable class:

namespace MyIterators;

class MyCollection implements \Iterator, \Countable {
    protected position = 0;

    protected entries = [];

    public function count()
    {
        return count(this->entries);
    }

    public function rewind() -> void
    {
        let this->position = 0;
    }

    public function current()
    {
        return this->entries[this->position];
    }

    public function key()
    {
        return this->position;
    }

    public function next() -> void
    {
        let this->position++;
    }

    public function valid()
    {
        return isset this->entries[this->position];
    }

    public function add(value) -> void
    {
        let this->entries[] = value;
    }

    public function merge(<MyCollection> collection) -> void
    {
        var value;

        for value in collection {
            this->add(value);
        }
    }
}

and a simple PHP script to test it

$a = new MyIterators\MyCollection();
$a->add('A');
$a->add('B');
$a->add('C');

foreach($a as $key => $value) {
    echo $key, ' => ', $value, PHP_EOL;
}
echo PHP_EOL;

$b = new MyIterators\MyCollection();
$b->add('X');
$b->add('Y');
$b->add('Z');

foreach($a as $key => $value) {
    echo $key, ' => ', $value, PHP_EOL;
}
echo PHP_EOL;

$a->rewind();
$b->rewind();

$a->merge($b);

foreach($a as $key => $value) {
    echo $key, ' => ', $value, PHP_EOL;
}
echo PHP_EOL;

PHP is able to iterate happily over each instance of the collection, so there's no problem there; but as soon as I call the merge() method which tries to iterate internally over the passed argument

        for value in collection {
            this->add(value);
        }

I get a fatal error from the collection

PHP Fatal error:  Uncaught exception 'Exception' with message 'The argument is not initialized or iterable()' in myiterators/mycollection.zep:50

The stack trace isn't particularly helpful

Stack trace:
#0 /home/zephir/myiterators/iteratorTest.php(29): MyIterators\MyCollection->merge(Object(MyIterators\MyCollection))
#1 {main}
  thrown in myiterators/mycollection.zep on line 50

But it seems that Zephir can't iterate over classes created in Zephir as iterable, even though a basic PHP script does see them as iterable.... or am I missing something fundamental?

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/26649304-doc-iterator-isn-t-iterable-internally?utm_campaign=plugin&utm_content=tracker%2F280146&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F280146&utm_medium=issues&utm_source=github).
steffengy commented 9 years ago

Does

for value in iterator(collection) {
      this->add(value);
}

work?

MarkBaker commented 9 years ago

Bingo, that works thanks.... is it documented anywhere?

steffengy commented 9 years ago

I think it's indeed missing in the official documentation, so the only "documentation" would unfortunately be a test case and the implementation for it.