Functional Programming wit SPL Iterators Marcus Brger international

  • Slides: 27
Download presentation
Functional Programming wit SPL Iterators Marcus Börger international PHP 2004 conference Marcus Börger Functional

Functional Programming wit SPL Iterators Marcus Börger international PHP 2004 conference Marcus Börger Functional programming with SPL Iterators

Functional Programming with SPL Iterators It is easy in a complex way - Lukas

Functional Programming with SPL Iterators It is easy in a complex way - Lukas Smith php conference 2004 þ þ Functional programming? Iterators þ þ Recursion using Iterators Filtering using Iterators Marcus Börger Functional programming with SPL Iterators 2

Functional programming? þ þ Abstract from the actual data (types) Implement algorithms without knowing

Functional programming? þ þ Abstract from the actual data (types) Implement algorithms without knowing the data Example: Sorting requires a container for elements Sorting requires element comparison Containers provide access to elements Sorting and Containers must not know data Marcus Börger Functional programming with SPL Iterators 3

What are Iterators þ Iterators are a concept to iterate anything that contains other

What are Iterators þ Iterators are a concept to iterate anything that contains other things. Examples: þ þ þ þ Values and Keys in an array Text lines in a file Database query results Files in a directory Elements or Attributes in XML Bits in an image Dates in a calendar range Iterators allow to encapsulate algorithms Marcus Börger Functional programming with SPL Iterators 4

The basic concepts þ Iterators can be internal or external also referred to as

The basic concepts þ Iterators can be internal or external also referred to as active or passive þ An internal iterator modifies the object itself þ An external iterator points to another object without modifying it þ PHP always uses external iterators at engine-level Marcus Börger Functional programming with SPL Iterators 5

The big difference Arrays þ þ require memory for all elements allow to access

The big difference Arrays þ þ require memory for all elements allow to access any element directly Iterators þ þ only know one element at a time only require memory for the current element forward access only Access done by method calls Marcus Börger Functional programming with SPL Iterators 6

PHP Iterators þ þ Anything that can be iterated implements Traversable User classes cannot

PHP Iterators þ þ Anything that can be iterated implements Traversable User classes cannot implement Traversable Aggregateis used for objects that use external iterators Iteratoris used for internal traversal or external iterators Marcus Börger Functional programming with SPL Iterators 7

Implementing Iterators Marcus Börger Functional programming with SPL Iterators 8

Implementing Iterators Marcus Börger Functional programming with SPL Iterators 8

How Iterators work þ Iterators can be used manually <? php $o = new

How Iterators work þ Iterators can be used manually <? php $o = new Array. Iterator(array(1, 2, 3)); $o->rewind(); while ($o->valid()) { $key = $o->key(); $val = $o->current(); // some code $o->next(); } ? > þ Iterators can be used implicitly with foreach <? php $o = new Array. Iterator(array(1, 2, 3)); foreach($o as $key => $val) { // some code } ? > Marcus Börger Functional programming with SPL Iterators 9

Array and property traversal þ Array. Objectallows external traversal of arrays þ Array. Objectcreates

Array and property traversal þ Array. Objectallows external traversal of arrays þ Array. Objectcreates Array. Iteratorinstances þ Multiple Array. Iteratorinstances can reference the same target with different states þ Both implement Seekable. Iteratorwhich allows to 'jump' to any position in the Array directly. Marcus Börger Functional programming with SPL Iterators 10

Array and property traversal Marcus Börger Functional programming with SPL Iterators 11

Array and property traversal Marcus Börger Functional programming with SPL Iterators 11

An example þ þ Reading a menu definition from an array Writing it to

An example þ þ Reading a menu definition from an array Writing it to the output Problem Handling of hierarchy Detecting recursion Formatting the output Marcus Börger Functional programming with SPL Iterators 12

Recursion with arrays þ A typical solution is to directly call array functions No

Recursion with arrays þ A typical solution is to directly call array functions No code reuse possible <? php function recurse_array($ar) { // do something before recursion while (!is_null(key($ar))) { if (is_array(current($ar))) { recurse_array(current($ar)); } // do something next($ar); } // do something after recursion } ? > Marcus Börger Functional programming with SPL Iterators 13

Detecting Recursion þ An array is recursive If the current element itself is an

Detecting Recursion þ An array is recursive If the current element itself is an Array In other words current() has children This is detectable by is_array() Recursing requires creating a new wrapper instance for the child array þ Recursive. Iterator is the interface to unify Recursion þ Recursive. Iterator handles the recursion þ þ class Recursive. Array. Iterator extends Array. Iterator implements Recursive. Iterator { function has. Children() { return is_array($this->current()); } function get. Children() { return new Recursive. Array. Iterator($this->current()); } } Marcus Börger Functional programming with SPL Iterators 14

Debug Session <? php $a = array('1', '2', array('31', '32'), '4'); $o = new

Debug Session <? php $a = array('1', '2', array('31', '32'), '4'); $o = new Recursive. Array. Iterator($a); $i = new Recursive. Iterator($o); foreach($i as $key => $val) { echo "$key => $valn"; } ? > 0 1 3 => => => 1 2 31 32 3 <? php class Recursive. Array. Iterator implements Recursive. Iterator { protected $ar; function __construct(Array $ar) { $this->ar = $ar; } function rewind() { reset($this->ar); } function valid() { return !is_null(key($this->ar)); } function key() { return key($this->ar); } function current() { return current($this->ar); } function next() { next($this->ar); } function has. Children() { return is_array(current($this->ar)); } function get. Children() { return new Recursive. Array. Iterator($this->current()); } } ? > Marcus Börger Functional programming with SPL Iterators 15

Making Array. Object recursive þ Change the class type of Array. Objects Iterator We

Making Array. Object recursive þ Change the class type of Array. Objects Iterator We simply need to change get. Iterator() <? php class Recursive. Array. Object extends Array. Object { function get. Iterator() { return new Recursive. Array. Iterator($this); } } ? > Marcus Börger Functional programming with SPL Iterators 16

Output HTML þ Problem how to format the output using </ul> Detecting recursion begin/end

Output HTML þ Problem how to format the output using </ul> Detecting recursion begin/end <? php class Menu. Output extends Recursive. Iterator { function __construct(Menu $m) { parent: : __construct($m); } function begin. Children() { echo str_repeat(' ', $this->get. Depth()). "<ul>n"; } function end. Children() { echo str_repeat(' ', $this->get. Depth()). "</ul>n"; } } ? > Marcus Börger Functional programming with SPL Iterators 17

Output HTML þ Problem how to write the output Echo the output within foreach

Output HTML þ Problem how to write the output Echo the output within foreach <ul> <li>1</li> <li>2</li> <ul> <li>31</li> <li>32</li> </ul> <li>4</li> </ul> <? php class Menu. Output extends Recursive. Iterator { function __construct(Menu $m) { parent: : __construct($m); } function begin. Children() { echo str_repeat(' ', $this->get. Depth()). "<ul>n"; } function end. Children() { echo str_repeat(' ', $this->get. Depth()+1). "</ul>n"; } } $ar = array('1', '2', array('31', '32'), '4'); $it = new Menu. Output(new Recursive. Array. Iterator($ar)); echo "<ul>n"; // for the intro foreach($it as $m) { echo str_repeat(' ', $it->get. Depth()+1). "<li>$m</li>n"; } echo "</ul>n"; // for the outro ? > Marcus Börger Functional programming with SPL Iterators 18

Filtering Problem Only recurse into active Menu elements Only show visible Menu elements Changes

Filtering Problem Only recurse into active Menu elements Only show visible Menu elements Changes prevent recurse_array from reuse <? php class Menu { function is. Active() // return true if active function is. Visible() // return true if visible } function recurse_array($ar) { // do something before recursion while (!is_null(key($ar))) { if (is_array(current($ar)) && current($ar)->is. Active()) { recurse_array(current($ar)); } if (current($ar)->current()->is. Active()) { // do something } next($ar); } // do something after recursion Marcus Börger Functional programming with SPL Iterators 19

Filtering Solution Filter the incoming data Unaccepted data simply needs to be skipped Do

Filtering Solution Filter the incoming data Unaccepted data simply needs to be skipped Do not accept inactive menu elements Using a Filter. Iterator <? php class Menu extends Recursive. Array. Iterator { function is. Active() // return true if active function is. Visible() // return true if visible } ? > Marcus Börger Functional programming with SPL Iterators 20

Filtering þ Using a Filter. Iterator <? php class Menu. Filter extends Filter. Iterator

Filtering þ Using a Filter. Iterator <? php class Menu. Filter extends Filter. Iterator implements Recursive. Iterator { function __construct(Menu $m) { parent: : __construct($m); } function accept() { return $this->current()->is. Visible(); } function has. Children() { return $this->current()->has. Children() && $this->current()->is. Active(); } function get. Children() { return new Menu. Filter($this->current()); } } ? > Marcus Börger Functional programming with SPL Iterators 21

Putting it together þ Make Menu. Output operate on Menu. Filter Pass a Menu

Putting it together þ Make Menu. Output operate on Menu. Filter Pass a Menu to the constructor (guarded by type hint) Create a Menu. Filter from the Menu. Filter implements Recursive. Iterator <? php class Menu. Output extends Recursive. Iterator { function __construct(Menu $m) { parent: : __construct(new Menu. Filter($m)); } function begin. Children() { echo "<ul>n"; } function end. Children() { echo "</ul>n"; } } ? > Marcus Börger Functional programming with SPL Iterators 22

What now þ þ If your menu structure comes from a database If your

What now þ þ If your menu structure comes from a database If your menu structure comes from XML You have to change Menu Detection of recursion works differently No single change in Menu. Output needed No single change in Menu. Filter needed Marcus Börger Functional programming with SPL Iterators 23

Using XML þ Change Menu to inherit from Simple. XMLIterator <? php class Menu

Using XML þ Change Menu to inherit from Simple. XMLIterator <? php class Menu extends Simple. XMLIterator { static function factory($xml) { return simplexml_load_string($xml, 'Menu'); } function is. Active() { return $this['active']; // access attribute } function is. Visible() { return $this['visible']; // access attribute } // get. Children already returns Menu instances } ? > Marcus Börger Functional programming with SPL Iterators 24

Using PDO þ Change Menu to read from database PDO PDO supports Iterator based

Using PDO þ Change Menu to read from database PDO PDO supports Iterator based access can create and read into objects will be available with PHP 5. 1 is under heavy development <? php $db = new PDO("mysql: //. . . "); $menu = $db->query("SELECT. . . FROM Menu. . . ", "Menu"); foreach ($menu as $m) { // fetch now returns Menu instances echo $m->fetch()->__to. String(); } ? > Marcus Börger Functional programming with SPL Iterators 25

Conclusion þ Iterators require a new way of programming þ Iterators allow to implement

Conclusion þ Iterators require a new way of programming þ Iterators allow to implement algorithms abstracted from data þ Iterators promote code reuse þ Some things are already in SPL þ Filtering þ Handling recursion Marcus Börger Functional programming with SPL Iterators 26

THANK YOU http: //somabo. de/talks/ http: //php. net/~helly/php/ext/spl Marcus Börger Functional programming with SPL

THANK YOU http: //somabo. de/talks/ http: //php. net/~helly/php/ext/spl Marcus Börger Functional programming with SPL Iterators 27