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) { 
             %> 
  • <%= $member["name"] %>
  • <% }); %>'; $ret = __::template($template, array('members'=>$members)); print_r($ret);

    returns…

  • bill
  • john
  • sarah
  • 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 to “Functional style programming with Underscore.php”

    Comments are closed.