yield
(generator)
About me
- I'm Tien
- I'm a PHP/Drupal developer
- I'm working at GO1
Outline
- What is yield/generator?
- Demo
- Simple usage
- Generator as object
- Saving memory
- Returning keys
- Pseudo keys
- Pass data to generator
- Why generator?
- How it work?
- When to use generator?
Do you know generator?
- return (80%)
- interator (20%)
What is generator?
- Is a Iterator.
- Return once item in array at a time.
- Look like a function, but behave like an iterator.
Iterator Interface
Iterator extends Traversable {
/* Methods */
abstract public mixed current ( void )
abstract public scalar key ( void )
abstract public void next ( void )
abstract public void rewind ( void )
abstract public boolean valid ( void )
}
How iterator work?
$it->rewind();
while ($it->valid())
{
$key = $it->key();
$value = $it->current();
// ...
$it->next();
}
Simple usage
function get_primes() {
yield 2;
$number = 3;
while (true) {
$prime = true;
for ($i = 2; $i <= ($number / 2); $i++) {
if (($number % $i) == 0) {
$prime = false;
break;
}
}
if ($prime) {
yield $number;
}
$number++;
}
}
foreach (get_primes() as $number) {
if ($number % 2 == 0) {
print $number;
break;
}
}
Saving memory demo
// Test 1
$m = memory_get_peak_usage();
foreach (line_one_by_one('file1.txt') as $l);
echo memory_get_peak_usage() - $m, "\n"; //Outputs 7248
// Test 2
$m = memory_get_peak_usage();
foreach (all_lines('file1.txt') as $l);
echo memory_get_peak_usage() - $m, "\n"; // Outputs 25668
Pseudo keys
- Just like array keys, but
- Can be any PHP datatype
- Can be duplicated
Peusedo keys
function get_items() {
yield array('a' => 2) => 3;
yield 'string' => 4;
yield 1.234 => 5;
yield function () {print 'hello';} => 6;
}
foreach (get_items() as $key => $value) {
if (is_callable($key)) {
call_user_func($key);
}
else if (is_array($key)) {
print_r($key);
}
else {
print $key;
}
print "=>";
print $value . "\n";
}
Pass data to generator
$logFileName = __DIR__ . '/error.log';
function logger($logFileName) {
$f = fopen($logFileName, 'a');
while ($logentry = yield) {
fwrite($f, (new DateTime())->format('Y-m-d H:i:s ') . $logentry . PHP_EOL);
}
}
$logger = logger($logFileName);
for ($i = 0; $i < 12; ++$i) {
$logger->send('Message #' . $i);
}
Generator as object
function xrange($min, $max) {
for ($i = $min; $i <= $max; $i++) {
yield $i;
}
}
$generator = xrange(0, 10);
while($generator->isValid()) {
echo $generator->key() . ' => ' . $generator->current() . ', ';
$generator->next();
}
// Print 0 => 0, 1 => 1 ...
Notes
- Can not return values inside generator
- Use 'return;' to terminate generator
Why generator?
- Reduce memory use
- Faster than iterating over an array
- Cleaner and shorter code
- Allows to start processing the first few values immediately
How it work?
When to use generator?
- Process large array
- Save memory
- Write clean code
References
- Documentation
- Wiki
- Nice presentation about generators
- Practical usage
yield
By Tiến Võ Xuân
yield
- 1,003