Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Generators: All About the Yield

Generators: All About the Yield

Presented at Nomad PHP EU 22 Mar 2018

Justin Yost

March 22, 2018
Tweet

More Decks by Justin Yost

Other Decks in Programming

Transcript

  1. What is a Generator? Think Iterators without the overhead of

    writing an Iterator. CC BY-NC 4.0 Justin Yost 2
  2. What is an Iterator? An Iterator, is a PHP object

    or iterator, that can be iterated itself internally. foreach ($iterator as $key => $value) {} CC BY-NC 4.0 Justin Yost 3
  3. What is a Generator? The big trick here is that

    Generators and Iterators provide for a looping mechanism without the memory overhead of the thing you are looping over. CC BY-NC 4.0 Justin Yost 4
  4. Iterator vs. Array vs. Generator — Iterators - Object Based,

    Rewind/Forward/Filter/etc, Limited memory usage — Array - Simple, One way, Direct Access, Memory constrained — Generator - Simple, One way, Limited memory usage CC BY-NC 4.0 Justin Yost 5
  5. Generators: All About the Yield yield - acts as the

    return from a generator CC BY-NC 4.0 Justin Yost 6
  6. Simple Example function getRange($max = 15) { for ($i =

    1; $i < $max; $i++) { yield $i; } } foreach(getRange(4) as $value) { echo "value: {$value} "; } // value: 1 value: 2 value: 3 CC BY-NC 4.0 Justin Yost 7
  7. Key and Value Yield Example function getRange($max = 15) {

    for ($i = 1; $i < $max; $i++) { yield $i => $max; } } foreach(getRange(4) as $key => $value) { echo "key: {$key} value: {$value} "; } // key: 1 value: 4 key: 2 value: 4 key: 3 value: 4 CC BY-NC 4.0 Justin Yost 8
  8. Empty Yield function getRange($max = 15) { for ($i =

    1; $i < $max; $i++) { yield; } } foreach(getRange(4) as $value) { echo "value: {$value} "; } // value: value: value: CC BY-NC 4.0 Justin Yost 9
  9. Yield by Reference function &getRange($max = 15) { for ($i

    = 1; $i < $max; $i++) { yield $i => $max; } } foreach(getRange(4) as &$key => $value) { echo "key: {$key} value: {$value} "; ($key++); } // key: 1 value: 4 key: 3 value: 4 CC BY-NC 4.0 Justin Yost 10
  10. Return function getRange($max = 15) { for ($i = 1;

    $i < $max; $i++) { yield $i; } return $max; } foreach($gen = getRange(4) as $key => $value) { echo "key: {$key} value: {$value} "; } echo $gen->getReturn(); // key: 0 value: 1 key: 1 value: 2 key: 2 value: 3 4 CC BY-NC 4.0 Justin Yost 11
  11. Early Return function getRange($max = 15) { for ($i =

    1; $i < $max; $i++) { yield $i; return; } } foreach($gen = getRange(4) as $key => $value) { echo "key: {$key} value: {$value} "; } echo $gen->getReturn(); // key: 0 value: 1 CC BY-NC 4.0 Justin Yost 12
  12. Generators — Generators are Iterators without the Iterator overhead —

    Generators can be interrupted in processing via yield — return ends a generator — You can operate a Generator using Iterator current, next, etc — Except for rewind, Generators are forward only Iterators CC BY-NC 4.0 Justin Yost 14
  13. Coroutines — Coroutines are programs that allow for non- preemptive

    multitasking via multiple entry points for suspending and returning. CC BY-NC 4.0 Justin Yost 15
  14. Generators and Coroutines — yield is the trick here, we

    can pause executing of one method and continue on in a different method CC BY-NC 4.0 Justin Yost 16
  15. Generators yield from function gen() { yield 1; yield 2;

    yield from gen2(); } function gen2() { yield 3; yield 4; } foreach (gen() as $val) { echo $val . " "; } // 1 2 3 4 CC BY-NC 4.0 Justin Yost 18
  16. Generators::send function genPrint() { while (true) { $string = yield;

    echo $string . " "; } } $print = genPrint(); // (instanceof Iterator && Generator) $print->send('fizz'); $print->send('buzz'); // fizz buzz CC BY-NC 4.0 Justin Yost 19
  17. Send and Receive function genPrint() { while (true) { $sent

    = (yield 'return-val '); echo $sent . PHP_EOL; } } $print = genPrint(); echo $print->send('fizz'); echo $print->send('buzz'); // fizz // return-val buzz // return-val CC BY-NC 4.0 Justin Yost 20
  18. Send and Receive — send executes the generator by passing

    the input — then yields the return value of the generator CC BY-NC 4.0 Justin Yost 21
  19. Send and Receive and Current function genPrint() { while (true)

    { $sent = (yield 'return-val '); echo $sent . PHP_EOL; } } $print = genPrint(); echo $print->current(); echo $print->send('fizz'); echo $print->send('buzz'); // return-val fizz // return-val buzz // return-val CC BY-NC 4.0 Justin Yost 22
  20. Send and Receive and Current — send executes the generator

    by passing the input — then yields the return value of the generator — current just yields the return value of the generator CC BY-NC 4.0 Justin Yost 23
  21. Multiple Yields with Send and Receive and Current function genPrint()

    { while (true) { $sent = (yield 'return-val '); echo $sent . PHP_EOL; $sent = (yield 'return-val2 '); echo $sent . PHP_EOL; } } $print = genPrint(); echo $print->current(); echo $print->send('fizz'); echo $print->send('buzz'); // return-val fizz // return-val2 buzz // return-val CC BY-NC 4.0 Justin Yost 24
  22. Multiple Yields with Send and Receive and Current — send

    executes the generator by passing the input — then yields the return value of the generator — current just yields the return value of the generator — each yield means we have another exit depending on where in the iteration we are — each iteration - first yield then second, then loop, repeat CC BY-NC 4.0 Justin Yost 25