Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
201 views
in Technique[技术] by (71.8m points)

What PHP code accessing Iterator interface is equivalent to a foreach loop?

Assume we have an Iteraror. What code is equivalent to foreaching it?

function foreach_(Iterator $i): void
{
    foreach ($i as $k => $v) {
    }
}
question from:https://stackoverflow.com/questions/65867805/what-php-code-accessing-iterator-interface-is-equivalent-to-a-foreach-loop

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The following code is equivalent:

function for_(Iterator $i): void
{
    for ($i->rewind(); $i->valid(); $i->next()) {
        $i->current();
        $i->key();
    }
}

Here is how I tested:

class IteratorTest extends TestCase
{
    /**
     * @dataProvider provide
     */
    public function testDoesTheSameWithIterator(
        Iterator $i, 
        callable $expectedFn, 
        callable $actualFn
    ): void {
        $expectedI = new Iterator_($i);
        $actualI = new Iterator_($i);

        $expectedFn($expectedI);
        $actualFn($actualI);

        var_export($expectedI->calls);
        self::assertSame($expectedI->calls, $actualI->calls);
    }

    public function provide(): array
    {
        return [
            'for iterator vs foreach' => [
                new ArrayIterator(['a' => 1, 2 => 'b', 3 => null]),
                __NAMESPACE__ . 'foreach_',
                __NAMESPACE__ . 'for_',
            ],
        ];
    }
}

class Iterator_ implements Iterator
{
    public array $calls = [];
    private Iterator $i;

    public function __construct(Iterator $i)
    {
        $this->i = $i;
    }

    public function __call($method, $arguments)
    {
        $return = $this->i->$method(...$arguments);
        $this->calls[] = compact('method', 'arguments', 'return');
        return $return;
    }

    public function current()
    {
        return $this->__call(__FUNCTION__, func_get_args());
    }

    public function next(): void
    {
        $this->__call(__FUNCTION__, func_get_args());
    }

    public function key()
    {
        return $this->__call(__FUNCTION__, func_get_args());
    }

    public function valid(): bool
    {
        return $this->__call(__FUNCTION__, func_get_args());
    }

    public function rewind(): void
    {
        $this->__call(__FUNCTION__, func_get_args());
    }
}

Here's what the test outputs:

array (
  0 => 
  array (
    'method' => 'rewind',
    'arguments' => 
    array (
    ),
    'return' => NULL,
  ),
  1 => 
  array (
    'method' => 'valid',
    'arguments' => 
    array (
    ),
    'return' => true,
  ),
  2 => 
  array (
    'method' => 'current',
    'arguments' => 
    array (
    ),
    'return' => 1,
  ),
  3 => 
  array (
    'method' => 'key',
    'arguments' => 
    array (
    ),
    'return' => 'a',
  ),
  4 => 
  array (
    'method' => 'next',
    'arguments' => 
    array (
    ),
    'return' => NULL,
  ),
  5 => 
  array (
    'method' => 'valid',
    'arguments' => 
    array (
    ),
    'return' => true,
  ),
  6 => 
  array (
    'method' => 'current',
    'arguments' => 
    array (
    ),
    'return' => 'b',
  ),
  7 => 
  array (
    'method' => 'key',
    'arguments' => 
    array (
    ),
    'return' => 2,
  ),
  8 => 
  array (
    'method' => 'next',
    'arguments' => 
    array (
    ),
    'return' => NULL,
  ),
  9 => 
  array (
    'method' => 'valid',
    'arguments' => 
    array (
    ),
    'return' => true,
  ),
  10 => 
  array (
    'method' => 'current',
    'arguments' => 
    array (
    ),
    'return' => NULL,
  ),
  11 => 
  array (
    'method' => 'key',
    'arguments' => 
    array (
    ),
    'return' => 3,
  ),
  12 => 
  array (
    'method' => 'next',
    'arguments' => 
    array (
    ),
    'return' => NULL,
  ),
  13 => 
  array (
    'method' => 'valid',
    'arguments' => 
    array (
    ),
    'return' => false,
  ),
)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...