[RESOLU] Generateur ignore yield une fois sur deux

Eléphant du PHP | 65 Messages

18 août 2016, 11:32

Bonjour à tous,
J'ai appris qu'un générateur se met en pause lorsqu'il rencontre un yield en attente d'être appelé, du coup je n'arrive pas à comprendre pourquoi mon yield est ignoré :

Code : Tout sélectionner

<?php function generator() { for($i = 0; $i < 5; $i++): echo "Début $i<br />"; echo yield; echo "Fin $i<hr />"; endfor; } $monGen = generator(); foreach ($monGen as $key => $value): $monGen->send('Hello<br />'); endforeach; ?>
Retourne :
Début 0
Hello
Fin 0

Début 1
Fin 1

Début 2
Hello
Fin 2

Début 3
Fin 3

Début 4
Hello
Fin 4
Notez que si je ne passe pas par une boucle foreach et que je fais manuellement chaque $monGen->send() le générateur se comporte correctement.
Vous avez une idée ?

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

18 août 2016, 13:48

Bonjour,

Je n'ai jamais utilisé yield, mais les exemples de la doc ne ressemblent pas à ce que tu as fait :
https://secure.php.net/manual/fr/langua ... ures.yield
Quand tout le reste a échoué, lisez le mode d'emploi...

Eléphant du PHP | 65 Messages

18 août 2016, 14:52

En fait dans les exemples ils utilisent yield pour renvoyer quelque chose, dans cet exemple je fais l'inverse, j'envoie quelque chose au générateur à l'aide de la méthode generator::send(), j'ai juste voulu bidouiller (comme d'hab).
Du coup j'ai compris pourquoi ça marche pas en fait lorsque la boucle for fait un tour elle initie un second tour jusqu'au "yield", à partir de là il y a un conflit avec la boucle foreach car lorsqu'on fait echo yield ou yield seul, même si il n'y a pas de valeur pour le yield celui-ci renvoit "null". Comme un générateur est un itérateur, il change sa clé, la boucle foreach étant liée au générateur, après avoir renvoyé le yeld null on a une boucle foreach qui envoie un résultat sur 2. On a donc un générateur qui fait 2 tour de boucle for avant de passer le relaie à foreach.

J'ai du mal à m'exprimer mais on voit très bien ce qu'il se passe avec var_dump() :
Début 0
Hello
Fin 0

Début 1
E:\users\...\generator7.php:18:null
Fin 1

Début 2
Hello
Fin 2

Début 3
E:\users\...\generator7.php:18:null
Fin 3

Début 4
Hello
Fin 4

E:\users\...\generator7.php:18:null
Voilà c'était une expérience inutile mais c'est toujours intéressant de comprendre pourquoi ça marche pas #-o