Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Code Samples CC BY-NC 4.0 Justin Yost 13

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Code Example CC BY-NC 4.0 Justin Yost 28

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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