Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using php yield / Generator::send() for a "data output stream"

I know that yield can be used to create a data iterator, e.g. to read data from a CSV file.

function csv_generator($file) {    
  $handle = fopen($file,"r");
  while (!feof($handle)) {
    yield fgetcsv($file);
  }
  fclose($file);
}

But the Generator::send() method suggests that I can do the same for sequential writing, instead of reading.

E.g. I want to use the thing like this:

function csv_output_generator($file) {
  $handle = fopen('file.csv', 'w');
  while (null !== $row = yield) {
    fputcsv($handle, $row);
  }
  fclose($handle);
}

$output_generator = csv_output_generator($file);
$output_generator->send($rows[0]);
$output_generator->send($rows[1]);
$output_generator->send($rows[2]);
// Close the output generator.
$output_generator->send(null);

The above will work, I think.

But $output_generator->send(null); for closing seems wrong, or not ideal. It means that I can never send a literal null. Which is ok for csv writing, but maybe there is a use case for sending null.

Is there any "best practice" for using php generators for sequential writing?

like image 295
donquixote Avatar asked Nov 09 '22 06:11

donquixote


1 Answers

Not saying this is a marvelous idea but if you're talking semantics, this 'feels' great.

Check against a class. Like pass in objects of a particular class to terminate the generator. Like:

// should probably use namespacing here.
class GeneratorUtilClose {}

class GeneratorUtil {
    public static function close() {
        return new GeneratorUtilClose;
    }
}

function csv_output_generator($file) {
  $handle = fopen('file.csv', 'w');

  while (!(($row = yield) instanceof GeneratorUtilClose)) {
    fputcsv($handle, $row);
  }

  fclose($handle);
}

$output_generator = csv_output_generator($file);
$output_generator->send($rows[0]);
$output_generator->send(GeneratorUtil::close());

Added a little factory in here for extra semantic sugar.

like image 194
Omran Jamal Avatar answered Nov 14 '22 23:11

Omran Jamal