Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

TURN ON THE GENERATOR

Slide 5

Slide 5 text

ARRAYS $coordinates = [ [039.842286, -108.457031], [032.916485, -113.906250], [033.431441, -099.404297], [042.032974, -097.031250], [050.064192, -106.962891], ]; foreach ($coordinates as $coordinate) { CDC::innoculate($coordinate); } print "innoculate " . count($coordinates) . " places"; $filter = function($coordinate) { return $coordinate[1] < -98; }; $breakouts = array_filter($coordinates, $filter);

Slide 6

Slide 6 text

THINGS LIKE ARRAYS $secret = new DomDocument(); $secret->loadHTMLFile( "secure/2021/lockdown-protocols.html" ); $steps = $secret->getElementsByTagName("h1"); foreach ($steps as $step) { Military::follow($step); } print "followed " . $steps->length . " steps";

Slide 7

Slide 7 text

THINGS LIKE ARRAYS is_array($coordinates) // 㱺 true is_array($steps) // 㱺 false $coordinates instanceof Traversable // 㱺 error $steps instanceof Traversable // 㱺 true

Slide 8

Slide 8 text

THINGS LIKE ARRAYS class ContainmentProtocols implements Traversable { } // 㱺 error

Slide 9

Slide 9 text

ITERATORS class EvacuationProcedures implements Iterator { function current(); function key(); function next(); function rewind(); function valid(); }

Slide 10

Slide 10 text

ITERATORS class EvacuationProcedures implements Iterator { /** * Returns the current value * where the array is at */ function current(); function key(); function next(); function rewind(); function valid(); }

Slide 11

Slide 11 text

ITERATORS class EvacuationProcedures implements Iterator { function current(); /** * Returns the pointer to * the current position */ function key(); function next(); function rewind(); function valid(); }

Slide 12

Slide 12 text

ITERATORS class EvacuationProcedures implements Iterator { function current(); function key(); /** * Advances the pointer to * the next position */ function next(); function rewind(); function valid(); }

Slide 13

Slide 13 text

ITERATORS class EvacuationProcedures implements Iterator { function current(); function key(); function next(); /** * Moves the pointer back * to the beginning */ function rewind(); function valid(); }

Slide 14

Slide 14 text

ITERATORS class EvacuationProcedures implements Iterator { function current(); function key(); function next(); function rewind(); /** * Indicates whether there * are more values to go */ function valid(); }

Slide 15

Slide 15 text

ABSTRACTION

Slide 16

Slide 16 text

ABSTRACTION function numberForPatient($patient) { return Registry::getNewNumber($patient); } function admitPatients(array $patients) { $numbers = array_map( "numberForPatient", $patients ); for ($i = 0; $i < count($patients); $i++) { Station::assignPatientToRoom( $numbers[$i], $patients[$i] ); } }

Slide 17

Slide 17 text

ABSTRACTION class Patients implements Iterator { // ... function key() { return $this->patients[ $this->pointer ]; } function current() { return numberForPatient( $this->key() ); } }

Slide 18

Slide 18 text

ABSTRACTION $intake = [ "Cathy", "Cal", "Joe", ]; $patients = new Patients($intake); foreach ($patients as $patient => $number) { Station::assignPatientToRoom( $number, $patient ); }

Slide 19

Slide 19 text

ABSTRACTION class ClassifiedPatients implements Iterator { // ...construct($patients) function key() { return md5( $this->patients->key() ); } }

Slide 20

Slide 20 text

ABSTRACTION $intake = [ "Cathy", "Cal", "Joe", ]; $patients = new ClassifiedPatients( new Patients($intake) ); foreach ($patients as $patient => $number) { Station::assignPatientToRoom( $number, $patient ); }

Slide 21

Slide 21 text

ABSTRACTION class SearchablePatients implements IteratorAggregate { // ...construct($patients) function getIterator() { return $this->patients; } function searchFor($patient) { $i = 0; for ($this->patients as $next => $number) { if ($patient == $next) { return $i; } $i++; } } }

Slide 22

Slide 22 text

ABSTRACTION class CountablePatients implements IteratorAggregate, Countable { // ...construct($patients) function count() { return iterator_count($this->patients); } } $countable = new CountablePatients( new Patients($intake) ); count($countable); // 㱺 3

Slide 23

Slide 23 text

ABSTRACTION class SeekablePatients implements IteratorAggregate, SeekableIterator { // ...construct($patients) function seek($position) { $i = 0; foreach ($this->patients as $patient) { if ($i++ == $position) { return; } } } } $seekable = new SeekablePatients( new Patients($intake) ); $seekable ->seek(1) ->current(); // 㱺 "Cal"

Slide 24

Slide 24 text

ABSTRACTION class ArrayablePatients implements IteratorAggregate, ArrayAccess { // ...construct($patients) function offsetExists($offset); function offsetGet($offset); function offsetSet($offset, $value); function offsetUnset($offset); } $array = new ArrayablePatients( new Patients($intake) ); $array[1]; // 㱺 "Cal"

Slide 25

Slide 25 text

ABSTRACTION • AppendIterator • ArrayIterator • CachingIterator • CallbackFilterIterator • DirectoryIterator • EmptyIterator • FilesystemIterator • FilterIterator • GlobIterator

Slide 26

Slide 26 text

ABSTRACTION • InfiniteIterator • IteratorIterator • LimitIterator • Mul0pleIterator • NoRewindIterator • ParentIterator • RecursiveArrayIterator • RecursiveCachingIterator • RecursiveCallbackFilterIterator

Slide 27

Slide 27 text

ABSTRACTION • RecursiveDirectoryIterator • RecursiveFilterIterator • RecursiveIteratorIterator • RecursiveRegexIterator • RecursiveTreeIterator • RegexIterator

Slide 28

Slide 28 text

PROBLEMS $patients = new Patients($intake); array_filter($patients, function($number) { // 㱺 error });

Slide 29

Slide 29 text

PROBLEMS // github.com/nikic/iter $patients = new Patients($intake); iter\filter(function($number) { // 㱺 ok }, $patients);

Slide 30

Slide 30 text

PROBLEMS // github.com/nikic/iter $patients = new Patients($intake); iter\filter(function($number) { // 㱺 ok }, $patients);

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

ABSTRACTION

Slide 34

Slide 34 text

ABSTRACTION $instructions = ""; $chapters = file_get_contents( "delta/operating-manual.txt" ); foreach ($chapters as $chapter) { $instructions .= file_get_contents( "delta/operating-manual/" . $chapter ); } print "instructions: \n\n" . $instructions; print "you've escaped!";

Slide 35

Slide 35 text

ABSTRACTION class OperatingManual implements Iterator { private $chapters; function __construct($file) { $this->chapters = file_get_contents( $file ); } }

Slide 36

Slide 36 text

ABSTRACTION class OperatingManual implements Iterator { // ... private $chapter = 0; function rewind() { $this->chapter = 0; } function next() { $this->chapter++; } }

Slide 37

Slide 37 text

ABSTRACTION class OperatingManual implements Iterator { // ... function key() { return $this->chapter[ $this->chapter ]; } function current() { return file_get_contents( $this->key() ); } function valid() { isset( $this->chapters[ $this->chapter ] ); } }

Slide 38

Slide 38 text

ABSTRACTION $manual = new OperatingManual( "delta/operating-manual.txt" ); foreach ($manual as $chapter) { print "next chapter: \n\n" . $chapter; } print "you've escaped!";

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

ABSTRACTION $manual = new OperatingManual( "delta/operating-manual.txt" ); foreach ($manual as $chapter) { print "next chapter: \n\n" . $chapter; } print "you've escaped!";

Slide 43

Slide 43 text

ITERATOR LIKE THINGS function OperatingManual($file) { $handle = fopen($file, "r"); while (!feof($handle)) { yield file_get_contents( trim(fgets($handle)) ); } fclose($handle); } $manual = OperatingManual( "delta/operating-manual.txt" );

Slide 44

Slide 44 text

ITERATOR LIKE THINGS print_r(get_class_methods($manual)); // 㱺 Array // ( // [0] => rewind // [1] => valid // [2] => current // [3] => key // [4] => next // [5] => send // [6] => throw // [7] => getReturn // [8] => __wakeup // )

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

ARRAYS ARE LIKE ROLODEXES

Slide 47

Slide 47 text

ASK FOR ITEM #3, AND YOU'LL GET ITEM #3

Slide 48

Slide 48 text

IT'S PREDICTABLE

Slide 49

Slide 49 text

FUNCTIONS ACT LIKE DATA TABLES

Slide 50

Slide 50 text

PUT THE SAME THING IN...

Slide 51

Slide 51 text

...YOU GET THE SAME THING OUT

Slide 52

Slide 52 text

IT'S PREDICTABLE

Slide 53

Slide 53 text

NULL OBJECT PATTERN

Slide 54

Slide 54 text

NULL OBJECT PATTERN function arrayToObject(array $data) { $encoded = json_encode($data); return json_decode($encoded); } $report = arrayToObject([ "station" => [ "armory" => [ "safe" => [ "weapons" => "one rifle", ], ], ], ]);

Slide 55

Slide 55 text

NULL OBJECT PATTERN function searchForWeapons($report) { return $report ->station ->armory ->safe ->weapons; } print searchForWeapons( arrayToObject(["station" => null]) ); // 㱺 error: accessing $armory on null

Slide 56

Slide 56 text

NULL OBJECT PATTERN function searchForWeapons($report) { if ($station = $report->station) { if ($armory = $station->armory) { // ... } } }

Slide 57

Slide 57 text

NULL OBJECT PATTERN class Maybe { private $value; function __construct($value) { $this->value = $value; } function __get($property) { if (is_object($this->value)) { return new static( $this->value->$property ); } } function value() { return $this->value; } }

Slide 58

Slide 58 text

NULL OBJECT PATTERN function searchForWeapons($report) { return $report ->station ->armory ->safe ->weapons ->value(); } print searchForWeapons( arrayToObject(["station" => null]); ); // 㱺 null

Slide 59

Slide 59 text

NULL OBJECT PATTERN static function from($value) { if ($value instanceof static) { return $value; } return new static($value); } static function generator($starting, $generator) { $monad = static::from($starting); $generator = $generator($monad); $next = $generator->current(); while ($generator->valid()) { $monad = static::from($next); $next = $generator->send($monad); } return $generator->getReturn(); }

Slide 60

Slide 60 text

NULL OBJECT PATTERN $weapons = Maybe::generator( $report, function($report) { $station = yield $report->station; $armory = yield $station->armory; $safe = yield $armory->safe; return $safe->weapons; } ); print $weapons;

Slide 61

Slide 61 text

COROUTINES

Slide 62

Slide 62 text

COROUTINES $people = [ "Lorna", "Rob", "Chris", "Aaron", "Sara", ]; $fences = [ "next to the old car", "behind the kennel", "out back", ];

Slide 63

Slide 63 text

COROUTINES function checkRations(array $people) { foreach ($people as $person) { print "checking rations for " . $person; yield showRationsFor($person); } } function watchFences(array $people, array $fences) { foreach ($fences as $fence) { $next = next($people); if ($next) { $next = reset($people); } print $next . " is watching " . $fence; yield watchFence($next, $fence); } }

Slide 64

Slide 64 text

COROUTINES class Task { private $generator; function __construct($generator) { $this->generator = $generator; } function run() { $this->generator->next(); } function valid() { return $this->generator->valid(); } }

Slide 65

Slide 65 text

COROUTINES class Manager { private $tasks = []; function addTask(Task $task) { array_unshift($this->tasks, $task); } function run() { while (count($this->tasks)) { $next = array_pop($this->tasks); $next->run(); if ($next->valid()) { $this->addTask($next); } } } }

Slide 66

Slide 66 text

COROUTINES $manager = new Manager(); $manager->addTask( new Task(checkRations($people) ); $manager->addTask( new Task(watchFences($people, $fences) ); $manager->run(); // 㱺 checking rations for Lorna // 㱺 Lorna is watching next to the old car // 㱺 checking rations for Rob // 㱺 Rob is watching behind the kennel // 㱺 checking rations for Chris // 㱺 Chris is watching out back // 㱺 checking rations for Aaron // 㱺 checking rations for Sara

Slide 67

Slide 67 text

COROUTINES $manager = new Manager(); $manager->addTask( new Task(checkRations($people) ); $manager->addTask( new Task(watchFences($people, $fences) ); $manager->run(); // 㱺 checking rations for Lorna // 㱺 Lorna is watching next to the old car // 㱺 checking rations for Rob // 㱺 Rob is watching behind the kennel // 㱺 checking rations for Chris // 㱺 Chris is watching out back // 㱺 checking rations for Aaron // 㱺 checking rations for Sara

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

No content