Bug #80010 [Com]: No error notification or throw when returning iterator from iterator method

From: Date: Mon, 24 Aug 2020 15:02:12 +0000
Subject: Bug #80010 [Com]: No error notification or throw when returning iterator from iterator method
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-228740@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=80010&edit=1

 ID:                 80010
 Comment by:         petr dot vejchoda at seznam dot cz
 Reported by:        petr dot vejchoda at seznam dot cz
 Summary:            No error notification or throw when returning
                     iterator from iterator method
 Status:             Not a bug
 Type:               Bug
 Package:            Class/Object related
 Operating System:   Win10
 PHP Version:        7.3.21
 Block user comment: N
 Private report:     N

 New Comment:

I mean seriously. It's just some sugar for stuff that nobody needs. Croutines returning values
could as well be classes that have getReturn() method and getIterator() method; Tadaa! Why the hell
do we need this stuff?? Seriously. Making mess in the language.


Previous Comments:
------------------------------------------------------------------------
[2020-08-24 14:56:05] petr dot vejchoda at seznam dot cz

Ok, I get it now. So why do generators need return value? Because yeah, in Unity coroutines are
poorly designed and yielded values from coroutines could only be used for passing execution
information. Is that the case in PHP too? Did you poorly designed coroutines too and thus made this
whole syntax up? I mean I never used coroutines in PHP. But wouldn't just common method
finished() and current() suffice? If you need to pass execution information together with value, you
can have type for that class XZ { $value; $nextExecution; }. Why do generators have to have a one
more unnecessary state? If using return is advance feature, why doesn't the advanced feature
have some advanced language syntax, instead of pure simple passing different generator from one
method to another having complex syntax? Shouldn't coroutines maybe have some additional
functionality instead of putting that into poor poor generators?
I get it ... still I don't like it.

------------------------------------------------------------------------
[2020-08-24 13:55:11] nikic@php.net

I have a hard time understanding what this bug report is about, but at a guess, you are probably
looking for "yield from", which is how you delegate to a different iterator.

Using "return" inside generators is an advanced feature that is only relevant when using
generators as coroutines.

------------------------------------------------------------------------
[2020-08-24 13:49:18] petr dot vejchoda at seznam dot cz

Ok, then tell me, what will happen in case I add foreach ($e as $value) { xy }; Which one will be
actually iterated through? How do I check whether function is iterator method or whether it just
returns Generator. In my case I wrongly typed everything as Iterator, but If I typed it as
Generator, it would be the same. I tried that.
This definitely leads to some very inconsistent behaviour. Or maybe consistently confusing.
This is actually the first time I hear, that methods in PHP return two values. Why in hell would you
allow such a thing with things as confusing as iterator functions.

------------------------------------------------------------------------
[2020-08-23 21:17:10] requinix@php.net

https://3v4l.org/bq2df

You didn't say it, but I assume what you're reporting is how the [4]=> output (the one
for $e) is an empty array.

    public function secondIterator(\Iterator $first): \Iterator
    {
        if ($this->whatever === true)
        {
            return $first;
        }

        foreach($first as $key=>$value)
        {
            yield $key => $value * $value;
        }
    }

Any function that contains a yield will always return a Generator. Always. Even if it returns before
it yields. The return value from a Generator function is kept separate from the yielded values.

https://www.php.net/manual/en/language.generators.syntax.php
https://www.php.net/manual/en/generator.getreturn.php

$e contains a Generator with no yielded items, and its getReturn() will give the passed iterator.

https://3v4l.org/bQJkN

------------------------------------------------------------------------
[2020-08-23 10:07:28] petr dot vejchoda at seznam dot cz

Description:
------------
When writing iterator method, complier lets me return Iterator variable, but it doesn't pass
it. I am actually at version 7.3.20 and I don't care to update. I read changelog.
Note value in $e in supplied code.

Test script:
---------------
class test
{
    private $whatever = false;

    public function __construct()
    {
        $a = iterator_to_array($this->firstIterator());
        $b = iterator_to_array($this->secondIterator($this->firstIterator()));
        $c = iterator_to_array($this->thirdIterator($this->firstIterator()));

        $this->whatever = true;
        $d = iterator_to_array($this->firstIterator());
        $e = iterator_to_array($this->secondIterator($this->firstIterator()));
        $f = iterator_to_array($this->thirdIterator($this->firstIterator()));

        var_dump([$a, $b, $c, $d, $e, $f]);
    }

    public function firstIterator(): \Iterator
    {
        yield 'a'=> 1;
        yield 'b'=> 2;
        yield 'c'=> 3;
    }

    public function secondIterator(\Iterator $first): \Iterator
    {
        if ($this->whatever === true)
        {
            return $first;
        }

        foreach($first as $key=>$value)
        {
            yield $key => $value * $value;
        }
    }

    public function thirdIterator(\Iterator $first): \Iterator
    {
        if ($this->whatever === true)
        {
            return $first;
        }

        return $this->thirdSubIterator($first);
    }

    public function thirdSubIterator(\Iterator $first): \Iterator
    {
        foreach($first as $key=>$value)
        {
            yield $key => $value * $value;
        }
    }
}

Expected result:
----------------
Returned Iterator should be either passed regularly or iterator method should not be accepted at all
as an iterator method, throwing exception



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



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


Thread (7 messages)

« previous php.bugs (#228740) next »