Functional style programming with Underscore.php

Underscore.php is a PHP port of the popular Underscore.js library. Underscore.php provides a utility library for PHP that provides a lot of the functional programming support that a programmer would expect in Ruby, but without adding much overhead during execution. The only caveat is that underscore.php requires PHP 5.3 or greater. Although you could accomplish some of the things using PHP’s built in functions, the functional style approach looks intuitive and easy to work with. Note that this not a purely functional programming like Haskell. It would be nice to integrate the library in your CakePHP framework, which will help bring some functional flavor to the framework.

Take a quick example of the ‘pluck’ method.

include_once('underscore.php');
 
$members= array(
  array('name'=>'bill', 'age'=>40, 'gender' => 'm'),
  array('name'=>'john', 'age'=>50, 'gender' => 'm'),
  array('name'=>'sarah','age'=>60, 'gender' => 'f')
);
 
$ret = __::pluck($members, 'name');
print_r($ret);


returns…

Array
(
    [0] => bill
    [1] => john
    [2] => sarah
)

Here is another using the ‘map’ method.

$ret = __::map(array(1, 2, 3), function($num) { return $num * 3; });
print_r($ret);

returns…

Array
(
    [0] => 3
    [1] => 6
    [2] => 9
)

Underscore.php works in both object-oriented and static styles. The following lines give the examples of both.

$members= array(
  array('name'=>'bill', 'age'=>40, 'gender' => 'm'),
  array('name'=>'john', 'age'=>50, 'gender' => 'm'),
  array('name'=>'sarah','age'=>60, 'gender' => 'f')
);
 
/* Static style */
$ret = __::max($members, function($member) { return $member['age']; });
 
/* Object Oriented style */
$ret = __($members)->max(function($member) { return $member['age']; });
 
print_r($ret);

returns…

Array
(
    [name] => sarah
    [age] => 60
    [gender] => f
)

Another example using the ‘template’ method.

$members = array(
  array('name'=>'bill', 'age'=>40, 'gender' => 'm'),
  array('name'=>'john', 'age'=>50, 'gender' => 'm'),
  array('name'=>'sarah','age'=>60, 'gender' => 'f')
);
 
$template = '<% __::each($members, function($member) { 
             %> <li><%= $member["name"] %></li> <% }); %>';
 
$ret = __::template($template, array('members'=>$members));
 
print_r($ret);

returns…

<li>bill</li>  
<li>john</li>  
<li>sarah</li>

How does it work

The underscore.php files defines a ‘__’ class which encapsulates all the functional methods and uses the functional programming ideas introduced in PHP 5.3.

// Underscore.php
 
class __ {
  // Return an array of values by mapping each item through the iterator
  public function map($collection=null, $iterator=null) {
     ...
  }
  .
  .
  /* other methods */
}

Presently the library supports the following methods.

Collections
each, map, reduce, reduceRight, detect, select, reject, all, any, includ, invoke, pluck, max, min, groupBy, sortBy, sortedIndex, toArray, size

Arrays
first, rest, last, compact, flatten, without, uniq, union, intersection, difference, zip, indexOf, lastIndexOf, range

Functions
memoize, throttle, once, after, wrap, compose

Objects
keys, values, functions, extend, defaults, clon, tap, isEqual, isEmpty, isObject, isArray, isFunction, isString, isNumber, isBoolean, isDate, isNaN, isNull

Utility
identity, times, mixin, uniqueId, template

Chaining
chain, value



One thought on “Functional style programming with Underscore.php

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>