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

Generators: All About the Yield

Generators: All About the Yield

Generators presentation given at PHP Detriot 2018

Justin Yost

July 27, 2018
Tweet

More Decks by Justin Yost

Other Decks in Programming

Transcript

  1. Generators: All About the Yield
    Justin Yost
    Senior Software Engineer at
    Wirecutter
    CC BY-NC 4.0 Justin Yost 1

    View Slide

  2. What is a Generator?
    Think Iterators without the overhead of writing an
    Iterator.
    CC BY-NC 4.0 Justin Yost 2

    View Slide

  3. What is an Iterator?
    An Iterator, is a PHP object or iterator, that can be
    iterated itself internally.
    so; arrays, generators and \Traversable
    foreach ($iterator as $key => $value) {}
    CC BY-NC 4.0 Justin Yost 3

    View Slide

  4. 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

    View Slide

  5. Iterator vs. Array vs. Generator
    — Iterators - Object Based, current/key/next/rewind/
    valid(), Advanced SPL Iterators, Limited memory
    usage
    — Array - Simple, One way, Direct Access, Memory
    constrained
    — Generator - Simple, One way, current/key/next(),
    Limited memory usage
    CC BY-NC 4.0 Justin Yost 5

    View Slide

  6. Generators: All About the Yield
    yield - acts as the return from a generator
    CC BY-NC 4.0 Justin Yost 6

    View Slide

  7. Simple Example
    function getRange($max = 15) {
    for ($i = 1; $i < $max; $i++) {
    yield $i; // PHP pauses here, passes $i back to the consumer
    }
    }
    foreach(getRange(4) as $value) {
    echo "value: {$value} ";
    }
    // value: 1 value: 2 value: 3
    CC BY-NC 4.0 Justin Yost 7

    View Slide

  8. 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

    View Slide

  9. 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

    View Slide

  10. 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

    View Slide

  11. 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

    View Slide

  12. 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

    View Slide

  13. Code Samples
    CC BY-NC 4.0 Justin Yost 13

    View Slide

  14. 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, key methods
    — Except for rewind, Generators are forward only
    Iterators
    CC BY-NC 4.0 Justin Yost 14

    View Slide

  15. 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

    View Slide

  16. 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

    View Slide

  17. More knowledge of Generators
    CC BY-NC 4.0 Justin Yost 17

    View Slide

  18. Generators yield from
    function gen() {
    yield 1; yield 2;
    yield from gen2();
    yield 5;
    }
    function gen2() {
    yield 3; yield 4;
    }
    foreach (gen() as $val) {
    echo $val . " ";
    }
    // 1 2 3 4 5
    CC BY-NC 4.0 Justin Yost 18

    View Slide

  19. 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

    View Slide

  20. 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

    View Slide

  21. Generators::send
    function genPrint() {
    for ($i = 1; $i < 15; $i++) {
    $string = (yield $i);
    echo $string . " ";
    }
    }
    $print = genPrint(); // (instanceof Iterator && Generator)
    echo $print->send('fizz'); echo $print->send('buzz');
    // fizz 2buzz 3
    CC BY-NC 4.0 Justin Yost 21

    View Slide

  22. 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 22

    View Slide

  23. 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 23

    View Slide

  24. Send and Receive and Current
    function genPrint() {
    for ($i = 1; $i < 15; $i++) {
    $sent = (yield $i);
    echo $sent . PHP_EOL;
    }
    }
    $print = genPrint();
    echo $print->current(); echo $print->send('fizz'); echo $print->send('buzz');
    // 1fizz
    // 2buzz
    // 3
    CC BY-NC 4.0 Justin Yost 24

    View Slide

  25. 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 25

    View Slide

  26. 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 26

    View Slide

  27. 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 27

    View Slide

  28. Code Example
    CC BY-NC 4.0 Justin Yost 28

    View Slide

  29. Sourced from:
    — https://scotch.io/tutorials/understanding-php-
    generators
    — https://nikic.github.io/2012/12/22/Cooperative-
    multitasking-using-coroutines-in-PHP.html
    CC BY-NC 4.0 Justin Yost 29

    View Slide

  30. Thanks/Questions?
    — twitter.com/justinyost
    — github.com/justinyost
    — justinyost.com
    — thewirecutter.com
    — linkedin.com/learning/instructors/justin-yost
    — https://joind.in/talk/7688b
    CC BY-NC 4.0 Justin Yost 30

    View Slide