php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65235 Unexpected behavior of the "yield"
Submitted: 2013-07-10 14:25 UTC Modified: 2013-07-10 14:31 UTC
From: shooric_ at mail dot ru Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.5.0 OS: Linux3.2.0-49
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: shooric_ at mail dot ru
New email:
PHP Version: OS:

 

 [2013-07-10 14:25 UTC] shooric_ at mail dot ru
Description:
------------
When you interrupt iterations on "yield" generator via "break" instruction, 
generator function does not work out until the end of.

Test script:
---------------
<?php
$filename = '111111.txt';
$h = fopen($filename, 'w+');
for($i = 0; $i < 7; $i++) {
    echo 'write: ' . $i . PHP_EOL;
    fwrite($h, $i . PHP_EOL);
}
fclose($h);
function file_line_iterator($filename) {
    echo 'open file' . PHP_EOL;
    $h = fopen($filename, 'r');
    while(false !== $line = fgets($h)) {
        echo 'yield: ' .  $line;
        yield $line;
    }
    echo 'close file' . PHP_EOL;
    fclose($h);
}
$k = 0;
foreach(file_line_iterator($filename) as $k => $v) {
    echo 'iterate: ' . $v;
    if(++$k > 4) {
        break;
    }
}

echo 'exit' . PHP_EOL;
exit;

Expected result:
----------------
write: 0
write: 1
write: 2
write: 3
write: 4
write: 5
write: 6
open file
yield: 0
iterate: 0
yield: 1
iterate: 1
yield: 2
iterate: 2
yield: 3
iterate: 3
yield: 4
iterate: 4

* close file

exit


Actual result:
--------------
write: 0
write: 1
write: 2
write: 3
write: 4
write: 5
write: 6
open file
yield: 0
iterate: 0
yield: 1
iterate: 1
yield: 2
iterate: 2
yield: 3
iterate: 3
yield: 4
iterate: 4
exit


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-07-10 14:31 UTC] nikic@php.net
-Status: Open +Status: Not a bug
 [2013-07-10 14:31 UTC] nikic@php.net
A generator will only run as far as you run it - that's the whole point of it. If you want to ensure that some piece of code is always run, even if you don't consume the generator to the end, you can use a finally block:

function file_line_iterator($filename) {
    $h = fopen($filename, 'r');
    try {
        while (false !== $line = fgets($h)) {
            yield $line;
        }
    } finally {
        fclose($h);
    }
}

In your particular case this is not necessary as PHP will automatically close the file when the generator is destroyed.
 [2013-07-10 14:58 UTC] shooric_ at mail dot ru
Ок, thanks
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sat May 03 15:01:28 2025 UTC