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

Generators: All About the Yield

Generators: All About the Yield

Presented at PHPVegas 07 Dec 2017

Justin Yost

December 07, 2017
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 . " "; } } $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 . " "; $sent = (yield 'return-val2 '); echo $sent . " "; } } $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