note 126068 added to generator.send

From: Date: Mon, 10 May 2021 20:09:38 +0000
Subject: note 126068 added to generator.send
Groups: php.notes 
Request: Send a blank email to php-notes+get-216369@lists.php.net to get a copy of this message
If you want to use generator::send() within a foreach loop, you will most likely get an unexpected result. The Generator::send() method resumes the generator, which means the pointer within the generator is moved to the next element in the generator list. Here is an example: <?php class ApiDummy { private static $apiDummyData = ['a', 'b', 'c', 'd', 'e']; public static function getAll(): Generator { foreach (self::$apiDummyData as $entry) { echo 'yielding $elem' . PHP_EOL; $newElem = (yield $entry); echo 'yield return: ' . $newElem . PHP_EOL; } } } $generator = ApiDummy::getAll(); // example iteration one with unexpected result foreach ($generator as $elem) { echo 'value from generator: ' . $elem . PHP_EOL; $generator->send($elem . '+'); } // example iteration two with the expected result while ($generator->valid()) { $elem = $generator->current(); echo 'value from generator: ' . $elem . PHP_EOL; $generator->send($elem . '+'); } ?> The result of example iteration one: yielding $elem value from generator: a yield return: a+ yielding $elem yield return: yielding $elem value from generator: c yield return: c+ yielding $elem yield return: yielding $elem value from generator: e yield return: e+ As you can see, the values b and d are not printed out and also not extended by the + sign. The foreach loop receives the first yield and the send call causes a second yield within the first loop. Therefor the second loop already receives the third yield and so on. To avoid this, one solution could be to use a while loop and the Generator::send() method to move the generator cursor forward and the Generator::current() method to retrieve the current value. The loop can be controlled with the Generator::valid() method which returns false, if the generator has finished. See example iterator two. The expected result of example iteration two: yielding $elem value from generator: a yield return: a+ yielding $elem value from generator: b yield return: b+ yielding $elem value from generator: c yield return: c+ yielding $elem value from generator: d yield return: d+ yielding $elem value from generator: e yield return: e+ ---- Server IP: 45.112.84.4 Probable Submitter: 45.112.85.242 (proxied: 2a04:4540:6812:8b00:6183:431e:7bd5:92f7) ---- Manual Page -- https://php.net/manual/en/generator.send.php Edit -- https://main.php.net/note/edit/126068 Del: integrated -- https://main.php.net/note/delete/126068/integrated Del: useless -- https://main.php.net/note/delete/126068/useless Del: bad code -- https://main.php.net/note/delete/126068/bad+code Del: spam -- https://main.php.net/note/delete/126068/spam Del: non-english -- https://main.php.net/note/delete/126068/non-english Del: in docs -- https://main.php.net/note/delete/126068/in+docs Del: other reasons-- https://main.php.net/note/delete/126068 Reject -- https://main.php.net/note/reject/126068 Search -- https://main.php.net/manage/user-notes.php

« previous php.notes (#216369) next »