Generating
Power with Yield/Jason Myers @jasonamyers
Yield, a modern language love
story
Originally Proposed in 1995, the yield keyword became official via the
RFP on June 20th 2013 with PHP 5.5.Generators
Facebook said a Hip, Hop and Don't Stop, and did their own yield
generators in HipHop PHP
They are HEAVILY BASED off of Python, with a nod towards the
Mozilla JS implementation and the await C# concept.
Generating Power with Yield
Generating Power with Yield
Iterator
An object that lets us traverse a container
Generating Power with Yield
PHP 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 )
}
For example checkout classArrayIterator
ArrayIterator Example
$fruits = array(
"apple" => "yummy",
"orange" => "ah ya, nice",
"grape" => "wow, I love it!",
"plum" => "nah, not me"
);
$obj = new ArrayObject( $fruits );
$it = $obj->getIterator();
echo "Iterating over: " . $obj->count() . " valuesn";
while( $it->valid() )
{
echo $it->key() . "=" . $it->current() . "n";
$it->next();
}
Iterating over: 4 values
apple=yummy
orange=ah ya, nice
grape=wow, I love it!
plum=nah, not me
Generator
a special routine that can be used to control the iteration behavior of
a loop, and yields the values one at a time
TL;DR
A generator looks like a function but behaves like an iterator
Generating Power with Yield
Performant?
range(0, 1000000)
Uses over 100MB of RAM
Generating Power with Yield
Generator Version
function xrange($start, $limit, $step = 1) {
if ($start < $limit) {
if ($step <= 0) {
throw new LogicException('Step must be +ve');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Step must be -ve');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
uses less than 1KB!
TL; DR
function xrange($min, $max) {
for ($i = $min; $i < $max; $i++) {
yield $i;
}
}
Sequences
function collatz($val) {
yield $val;
while ($val != 1) {
if ($val%2 == 0) {
$val /= 2;
} else {
$val = 3*$val + 1;
}
yield $val;
}
}
foreach (collatz(11) as $c) {
echo $c," ";
}
11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
Generating Power with Yield
Y U Only LOOPin?
It will work for any function that takes an Iterator or a Traversable as
argument
$arr = iterator_to_array(collatz(11));
Transformations
function multiply_sequence($a, $fac) {
foreach ($a as $val) {
yield $val*$fac;
}
}
function to_html_list($input) {
foreach ($input as $val) {
yield "<li>".$val."</li>";
}
}
Chaining
foreach (to_html_list(multiply_sequence(collatz(5),2)) as $val) {
echo $val,"n";
}
<li>10</li>
<li>32</li>
<li>16</li>
<li>8</li>
<li>4</li>
<li>2</li>
Selections
function select_pattern($input, $pattern) {
foreach ($input as $val) {
if (preg_match($pattern, $val)) {
yield $val;
}
}
}
Breath In
function getLines($file) {
$f = fopen($file, 'r');
if (!$f) {
throw new Exception();
}
while ($line = fgets($f)) {
yield $line;
}
fclose($f);
}
foreach (getLines("someFile") as $line) {
doSomethingWithLine($line);
}
Breath Out
function createLog($file) {
$f = fopen($file, 'a');
while (true) {
$line = yield;
fwrite($f, $line);
}
}
$log = createLog($file);
$log->send("First");
$log->send("Second");
$log->send("Third");
Generating Power with Yield
Bro Remote Me!
Fake the simultaneous processing of data
Generating Power with Yield
Green Threads
threads that are scheduled by a virtual machine (VM/interperter?)
instead of natively by the underlying operating system
function step1() {
$f = fopen("file.txt", 'r');
while ($line = fgets($f)) {
processLine($line);
yield true;
}
}
function step2() {
$f = fopen("file2.txt", 'r');
while ($line = fgets($f)) {
processLine($line);
yield true;
}
}
function step3() {
$f = fsockopen("www.example.com", 80);
stream_set_blocking($f, false);
$headers = "GET / HTTP/1.1rn";
$headers .= "Host: www.example.comrn";
$headers .= "Connection: Closernrn";
fwrite($f, $headers);
$body = '';
while (!feof($f)) {
$body .= fread($f, 8192);
yield true;
}
processBody($body);
}
function runner(array $steps) {
while (true) {
foreach ($steps as $key => $step) {
$step->next();
if (!$step->valid()) {
unset($steps[$key]);
}
}
if (empty($steps)) return;
}
}
runner(array(step1(), step2(), step3()));
ZOMG... THERE BE DRAGONS!
This relies on making sure we have no blocking IO
overREACTPHP much?
event based, non-blocking IO - ReActPHP
One More Thing
So if I can flip control, I can haz an Async?
class Buffer {
protected $reads, $data;
public function __construct() {
$this->reads = new SplQueue();
$this->data = new SplQueue();
}
public function read() {
if( $this->data->isEmpty() ) {
$deferred = new ReactPromiseDeferred();
$this->reads->enqueue($deferred->resolver());
return $deferred->promise();
} else {
return ReactPromiseWhen::resolve($this->data->dequeue());
}
}
public function write($str) {
if( $this->reads->isEmpty() ) {
$this->data->enqueue($str);
} else {
$this->reads->dequeue()->resolve($str);
}
}
}
function printer(Buffer $buffer) {
while( true ) {
$value = ( yield Util::async($buffer->read()) );
echo "Printer: ", $value, PHP_EOL;
yield Util::async(nested_printer($buffer));
}
}
function nested_printer(Buffer $buffer) {
for( $i = 0; $i < 5; $i++ ) {
// Yield a promise task and wait for the result - this is non-blocking
$value = ( yield Util::async($buffer->read()) );
echo "Nested printer: ", $value, PHP_EOL;
}
}
$buffer = new Buffer();
$scheduler = new AsyncScheduler();
$scheduler->add(new AsyncTaskGeneratorTask(printer($buffer)));
$i = 0;
$scheduler->add(new AsyncTaskRecurringTask(
function() use($buffer, &$i) { $buffer->write(++$i); }
));
$scheduler->run();
Printer: 1
Nested printer: 2
Nested printer: 3
Nested printer: 4
Nested printer: 5
Nested printer: 6
Printer: 7
Nested printer: 8
Nested printer: 9
Nested printer: 10
Nested printer: 11
Nested printer: 12
...
$loop = ReactEventLoopFactory::create();
$scheduler = new AsyncScheduler();
$scheduler->add(new AsyncTaskRecurringTask([$loop, 'tick']));
$scheduler->run();
Async
Created by Matt Pryor, on Bitbucket
Thanks
Huge thanks to Paul M. Jones and William Golden!
THE END
@jasonamyers

More Related Content

PDF
Advanced modulinos trial
PDF
Advanced modulinos
PDF
What is the difference between a good and a bad repository? (Forum PHP 2018)
PDF
WordPress: From Antispambot to Zeroize
PPT
php 2 Function creating, calling, PHP built-in function
ODP
PHP pod mikroskopom
PDF
Functional Structures in PHP
DOCX
Sadi service
Advanced modulinos trial
Advanced modulinos
What is the difference between a good and a bad repository? (Forum PHP 2018)
WordPress: From Antispambot to Zeroize
php 2 Function creating, calling, PHP built-in function
PHP pod mikroskopom
Functional Structures in PHP
Sadi service

What's hot (20)

DOCX
Example code for the SADI BMI Calculator Web Service
PPTX
Isset(), unset(), empty() 4
PDF
Orlando BarCamp Why Javascript Doesn't Suck
PDF
Data Types In PHP
PDF
Bag of tricks
ODP
Php variables (english)
PDF
Laravel the right way
PDF
TDC 2016 (Florianópolis) - Vá para o próximo nível - Dicas e truques para a c...
PDF
ZCPE - PHP Conference 2015
PDF
Web 9 | OOP in PHP
PDF
2014 database - course 2 - php
PDF
Web 4 | Core JavaScript
PDF
02 - Second meetup
PDF
You code sucks, let's fix it
PPTX
Zero to SOLID
PDF
De 0 a 100 con Bash Shell Scripting y AWK
PDF
Linux shell script-1
PDF
The most exciting features of PHP 7.1
PPT
Class 2 - Introduction to PHP
KEY
Intermediate PHP
Example code for the SADI BMI Calculator Web Service
Isset(), unset(), empty() 4
Orlando BarCamp Why Javascript Doesn't Suck
Data Types In PHP
Bag of tricks
Php variables (english)
Laravel the right way
TDC 2016 (Florianópolis) - Vá para o próximo nível - Dicas e truques para a c...
ZCPE - PHP Conference 2015
Web 9 | OOP in PHP
2014 database - course 2 - php
Web 4 | Core JavaScript
02 - Second meetup
You code sucks, let's fix it
Zero to SOLID
De 0 a 100 con Bash Shell Scripting y AWK
Linux shell script-1
The most exciting features of PHP 7.1
Class 2 - Introduction to PHP
Intermediate PHP
Ad

Similar to Generating Power with Yield (20)

ODP
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
ODP
Incredible Machine with Pipelines and Generators
ODP
The promise of asynchronous php
PDF
ReactPHP
ODP
The promise of asynchronous PHP
PDF
Dutch PHP Conference 2013: Distilled
KEY
CakePHP 2.0 - It'll rock your world
PDF
Php In A Nutshell A Desktop Quick Reference 1st Edition Paul Hudson
KEY
CakePHP - The Path to 2.0
PDF
From Generator to Fiber the Road to Coroutine in PHP
ODP
The promise of asynchronous PHP
PPTX
Electrify your code with PHP Generators
ODP
The promise of asynchronous php
KEY
Gearman and CodeIgniter
PDF
PHP Generators
PPTX
How to Supercharge your PHP Web API
PDF
React PHP: the NodeJS challenger
PDF
08 Advanced PHP #burningkeyboards
PPTX
Taming the resource tiger
PDF
Alexander Makarov "Let’s talk about code"
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
Incredible Machine with Pipelines and Generators
The promise of asynchronous php
ReactPHP
The promise of asynchronous PHP
Dutch PHP Conference 2013: Distilled
CakePHP 2.0 - It'll rock your world
Php In A Nutshell A Desktop Quick Reference 1st Edition Paul Hudson
CakePHP - The Path to 2.0
From Generator to Fiber the Road to Coroutine in PHP
The promise of asynchronous PHP
Electrify your code with PHP Generators
The promise of asynchronous php
Gearman and CodeIgniter
PHP Generators
How to Supercharge your PHP Web API
React PHP: the NodeJS challenger
08 Advanced PHP #burningkeyboards
Taming the resource tiger
Alexander Makarov "Let’s talk about code"
Ad

More from Jason Myers (11)

PDF
Python Static Analysis Tools
PDF
Introduction to SQLAlchemy ORM
PDF
Filling the flask
PDF
Building CLIs that Click
PDF
Spanning Tree Algorithm
PDF
Introduction to Pandas
PDF
SQLAlchemy Core: An Introduction
PDF
Introduction to SQLAlchemy and Alembic Migrations
PDF
Diabetes and Me: My Journey So Far
PDF
Selenium testing
PDF
Coderfaire Data Networking for Developers
Python Static Analysis Tools
Introduction to SQLAlchemy ORM
Filling the flask
Building CLIs that Click
Spanning Tree Algorithm
Introduction to Pandas
SQLAlchemy Core: An Introduction
Introduction to SQLAlchemy and Alembic Migrations
Diabetes and Me: My Journey So Far
Selenium testing
Coderfaire Data Networking for Developers

Recently uploaded (20)

PPTX
O2C Customer Invoices to Receipt V15A.pptx
PPTX
Modernising the Digital Integration Hub
PDF
A novel scalable deep ensemble learning framework for big data classification...
PDF
Getting Started with Data Integration: FME Form 101
PDF
DP Operators-handbook-extract for the Mautical Institute
PDF
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
PDF
Hindi spoken digit analysis for native and non-native speakers
PPT
What is a Computer? Input Devices /output devices
PDF
1 - Historical Antecedents, Social Consideration.pdf
PDF
Enhancing emotion recognition model for a student engagement use case through...
PDF
A Late Bloomer's Guide to GenAI: Ethics, Bias, and Effective Prompting - Boha...
PPTX
observCloud-Native Containerability and monitoring.pptx
PDF
Zenith AI: Advanced Artificial Intelligence
PPT
Geologic Time for studying geology for geologist
PDF
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
PDF
Hybrid model detection and classification of lung cancer
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
Taming the Chaos: How to Turn Unstructured Data into Decisions
PDF
WOOl fibre morphology and structure.pdf for textiles
PDF
Univ-Connecticut-ChatGPT-Presentaion.pdf
O2C Customer Invoices to Receipt V15A.pptx
Modernising the Digital Integration Hub
A novel scalable deep ensemble learning framework for big data classification...
Getting Started with Data Integration: FME Form 101
DP Operators-handbook-extract for the Mautical Institute
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
Hindi spoken digit analysis for native and non-native speakers
What is a Computer? Input Devices /output devices
1 - Historical Antecedents, Social Consideration.pdf
Enhancing emotion recognition model for a student engagement use case through...
A Late Bloomer's Guide to GenAI: Ethics, Bias, and Effective Prompting - Boha...
observCloud-Native Containerability and monitoring.pptx
Zenith AI: Advanced Artificial Intelligence
Geologic Time for studying geology for geologist
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
Hybrid model detection and classification of lung cancer
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Taming the Chaos: How to Turn Unstructured Data into Decisions
WOOl fibre morphology and structure.pdf for textiles
Univ-Connecticut-ChatGPT-Presentaion.pdf

Generating Power with Yield

  • 2. Yield, a modern language love story Originally Proposed in 1995, the yield keyword became official via the RFP on June 20th 2013 with PHP 5.5.Generators Facebook said a Hip, Hop and Don't Stop, and did their own yield generators in HipHop PHP
  • 3. They are HEAVILY BASED off of Python, with a nod towards the Mozilla JS implementation and the await C# concept.
  • 6. Iterator An object that lets us traverse a container
  • 8. PHP 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 ) } For example checkout classArrayIterator
  • 9. ArrayIterator Example $fruits = array( "apple" => "yummy", "orange" => "ah ya, nice", "grape" => "wow, I love it!", "plum" => "nah, not me" ); $obj = new ArrayObject( $fruits ); $it = $obj->getIterator(); echo "Iterating over: " . $obj->count() . " valuesn"; while( $it->valid() ) { echo $it->key() . "=" . $it->current() . "n"; $it->next(); } Iterating over: 4 values apple=yummy orange=ah ya, nice grape=wow, I love it! plum=nah, not me
  • 10. Generator a special routine that can be used to control the iteration behavior of a loop, and yields the values one at a time
  • 11. TL;DR A generator looks like a function but behaves like an iterator
  • 15. Generator Version function xrange($start, $limit, $step = 1) { if ($start < $limit) { if ($step <= 0) { throw new LogicException('Step must be +ve'); } for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } else { if ($step >= 0) { throw new LogicException('Step must be -ve'); } for ($i = $start; $i >= $limit; $i += $step) { yield $i; } } } uses less than 1KB!
  • 16. TL; DR function xrange($min, $max) { for ($i = $min; $i < $max; $i++) { yield $i; } }
  • 17. Sequences function collatz($val) { yield $val; while ($val != 1) { if ($val%2 == 0) { $val /= 2; } else { $val = 3*$val + 1; } yield $val; } } foreach (collatz(11) as $c) { echo $c," "; } 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
  • 19. Y U Only LOOPin? It will work for any function that takes an Iterator or a Traversable as argument $arr = iterator_to_array(collatz(11));
  • 20. Transformations function multiply_sequence($a, $fac) { foreach ($a as $val) { yield $val*$fac; } } function to_html_list($input) { foreach ($input as $val) { yield "<li>".$val."</li>"; } }
  • 21. Chaining foreach (to_html_list(multiply_sequence(collatz(5),2)) as $val) { echo $val,"n"; } <li>10</li> <li>32</li> <li>16</li> <li>8</li> <li>4</li> <li>2</li>
  • 22. Selections function select_pattern($input, $pattern) { foreach ($input as $val) { if (preg_match($pattern, $val)) { yield $val; } } }
  • 23. Breath In function getLines($file) { $f = fopen($file, 'r'); if (!$f) { throw new Exception(); } while ($line = fgets($f)) { yield $line; } fclose($f); } foreach (getLines("someFile") as $line) { doSomethingWithLine($line); }
  • 24. Breath Out function createLog($file) { $f = fopen($file, 'a'); while (true) { $line = yield; fwrite($f, $line); } } $log = createLog($file); $log->send("First"); $log->send("Second"); $log->send("Third");
  • 26. Bro Remote Me! Fake the simultaneous processing of data
  • 28. Green Threads threads that are scheduled by a virtual machine (VM/interperter?) instead of natively by the underlying operating system
  • 29. function step1() { $f = fopen("file.txt", 'r'); while ($line = fgets($f)) { processLine($line); yield true; } }
  • 30. function step2() { $f = fopen("file2.txt", 'r'); while ($line = fgets($f)) { processLine($line); yield true; } }
  • 31. function step3() { $f = fsockopen("www.example.com", 80); stream_set_blocking($f, false); $headers = "GET / HTTP/1.1rn"; $headers .= "Host: www.example.comrn"; $headers .= "Connection: Closernrn"; fwrite($f, $headers); $body = ''; while (!feof($f)) { $body .= fread($f, 8192); yield true; } processBody($body); }
  • 32. function runner(array $steps) { while (true) { foreach ($steps as $key => $step) { $step->next(); if (!$step->valid()) { unset($steps[$key]); } } if (empty($steps)) return; } } runner(array(step1(), step2(), step3()));
  • 33. ZOMG... THERE BE DRAGONS! This relies on making sure we have no blocking IO
  • 34. overREACTPHP much? event based, non-blocking IO - ReActPHP
  • 35. One More Thing So if I can flip control, I can haz an Async?
  • 36. class Buffer { protected $reads, $data; public function __construct() { $this->reads = new SplQueue(); $this->data = new SplQueue(); } public function read() { if( $this->data->isEmpty() ) { $deferred = new ReactPromiseDeferred(); $this->reads->enqueue($deferred->resolver()); return $deferred->promise(); } else { return ReactPromiseWhen::resolve($this->data->dequeue()); } } public function write($str) { if( $this->reads->isEmpty() ) { $this->data->enqueue($str); } else { $this->reads->dequeue()->resolve($str); } } }
  • 37. function printer(Buffer $buffer) { while( true ) { $value = ( yield Util::async($buffer->read()) ); echo "Printer: ", $value, PHP_EOL; yield Util::async(nested_printer($buffer)); } }
  • 38. function nested_printer(Buffer $buffer) { for( $i = 0; $i < 5; $i++ ) { // Yield a promise task and wait for the result - this is non-blocking $value = ( yield Util::async($buffer->read()) ); echo "Nested printer: ", $value, PHP_EOL; } }
  • 39. $buffer = new Buffer(); $scheduler = new AsyncScheduler(); $scheduler->add(new AsyncTaskGeneratorTask(printer($buffer))); $i = 0; $scheduler->add(new AsyncTaskRecurringTask( function() use($buffer, &$i) { $buffer->write(++$i); } )); $scheduler->run(); Printer: 1 Nested printer: 2 Nested printer: 3 Nested printer: 4 Nested printer: 5 Nested printer: 6 Printer: 7 Nested printer: 8 Nested printer: 9 Nested printer: 10 Nested printer: 11 Nested printer: 12 ...
  • 40. $loop = ReactEventLoopFactory::create(); $scheduler = new AsyncScheduler(); $scheduler->add(new AsyncTaskRecurringTask([$loop, 'tick'])); $scheduler->run();
  • 41. Async Created by Matt Pryor, on Bitbucket
  • 42. Thanks Huge thanks to Paul M. Jones and William Golden!