views:

803

answers:

3

In Python (and others), you can incrementally process large volumes of data by using the 'yield' operator in a function. What would be the similar way to do so in PHP?

For example, lets say in Python, if I wanted to read a potentially very large file, I could work on each line one at a time like so (this example is contrived, as it is basically the same thing as 'for line in file_obj'):

def file_lines(fname):
    f = open(fname)
    for line in f:
        yield line
    f.close()

for line in file_lines('somefile'):
    #process the line

What I'm doing right now (in PHP) is I'm using a private instance variable to keep track of state, and acting accordingly each time the function is called, but it seems like there must be a better way.

+3  A: 

Unfortunately, there isn't a language equivalent. The easiest way is to either to what you're already doing, or to create a object that uses instance variables to maintain state.

There is however a good option if you want to use the function in conjunction with the foreach-statement: SPL Iterators. They can be used to achieve something quite similar to python generators.

Emil H
Oh well, it was worth asking.
nilamo
+1  A: 

There may not be an equivalent operator, but the following code is equivalent in function and overhead:

function file_lines($file) {
  static $fhandle;

  if ( is_null($fhandle) ) {
    $fhandle = fopen($file, 'r');

    if ( $fhandle === false ) {
      return false;
    }
  }

  if ( ($line = fgets($fhandle))!== false ) {
    return $line;
  }


  fclose($fhandle);
  $fhandle = null;
}

while ( $line = file_lines('some_file') ) {
  // ...
}

That looks about right. Sorry, I haven't tested it.

Justin Johnson
+2  A: 

I prototype everything in Python before implementing in any other languages, including PHP. I ended up using callbacks to achieve what I would with the yield.

function doSomething($callback) 
{
    foreach ($something as $someOtherThing) {
        // do some computations that generates $data

        call_user_func($callback, $data);
    }
}

function myCallback($input)
{
    // save $input to DB 
    // log
    // send through a webservice
    // etc.
    var_dump($input);
}


doSomething('myCallback');

This way each $data is passed to the callback function and you can do what you want.

Luiz Damim