0

My current use case is I have a Generator that takes an iterable and uses yield from to return everything from it (similar to the example in the PHP docs). I have two examples below.

In this example, I am manually iterating through the Generator using Iterator methods: rewind(), valid(), current(), and next(). This example leads into an infinite loop and I never reach the var_dump call.

<?php

$arr = [10, 20, 30, 40, 50];
$itr = new ArrayIterator($arr);
    
function q() {
    global $itr;
    
    yield from $itr;
}

$a = [];

q()->rewind();
while (q()->valid()) {
    $a[q()->key()] = q()->current();
    
    q()->next();
}

var_dump($a); // I never reach this

In this example, I have a normal call to iterator_to_array() and it successfully completes.

<?php

$arr = [10, 20, 30, 40, 50];
$itr = new ArrayIterator($arr);
    
function q() {
    global $itr;
    
    yield from $itr;
}

$a = iterator_to_array(q());
var_dump($a);

I found a similar question but it's not quite the answer I'm looking for since that question ends up using iterator_to_array(). Similarly, the PHP docs advise using iterator_to_array with the use_keys parameter. But I'd like to make the while loop work if that's possible.

What am I doing wrong in the first example that is causing me to enter an infinite loop?

allejo
  • 2,076
  • 4
  • 25
  • 40
  • 1
    Every time you call `q()` you're getting a new generator, not continuing the previous generator. You should assign `q()` to a variable and reuse that. – Barmar Jan 12 '22 at 04:53
  • @Barmar I have been hitting my head against the wall on this for a while. You're absolutely right! `q()` is returning a new generator every time and storing it in a variable solves my problem. Thank you! – allejo Jan 12 '22 at 05:01

1 Answers1

0

If anyone else runs into the same problem I did, thanks to Barmar in the comments for solving it! In my use case, I'm creating a new generator each time I call q(), which meant I was never moving forward in the same instance.

Assigning the generator to a variable solves my problem,

<?php

$arr = [10, 20, 30, 40, 50];
$itr = new ArrayIterator($arr);
    
function q() {
    global $itr;
    
    yield from $itr;
}

$a = [];
$g = q();

$g->rewind();
while ($g->valid()) {
    $a[$g->key()] = $g->current();
    
    $g->next();
}

var_dump($a); // I never reach this
allejo
  • 2,076
  • 4
  • 25
  • 40