Map and Reduce in PHP

Sebastian Bergmann » 20 February 2008 » in PHP » 6 Comments

Just like Python, PHP is not a full-fledged functional language, but it supports some very useful functional idioms such as Map, Filter, and Reduce. A blog posting by Scott Moonen on Functional Python prompted me to write this posting on PHP's array_map(), array_filter(), and array_reduce() functions that apply callbacks to arrays.

Map

The array_map() function applies the callback to the elements of the given array(s) and returns the result. This example adds 1 to each element of the array:

<?php
print_r(
  array_map(
    create_function('$x', 'return $x + 1;'),
    array(1, 2, 3, 4, 5)
  )
);
?>
Array
(
    [0] => 2
    [1] => 3
    [2] => 4
    [3] => 5
    [4] => 6
)

Filter

The array_filter() function takes an array and a callback that returns a boolean value as its input and returns a new array containing only the elements for which the callback returns true.

<?php
print_r(
  array_filter(
    array(1, 2, 3, 4, 5),
    create_function('$x', 'return $x % 2 == 0;')
  )
);
?>
Array
(
    [1] => 2
    [3] => 4
)

Reduce

Provided with an array and a callback, array_reduce() reduces that array by applying the callback to pairs of elements in the array. An example is the best way to understand this. Let's say we want to find the sum of all the elements in an array:

<?php
print array_reduce(
  array(1, 2, 3, 4, 5),
  create_function('$x, $y', 'return $x + $y;')
);
?>
15

The examples above use PHP's create_function() function to create anonymous functions for the callbacks. True, this looks ugly. But maybe one day we get closures in PHP.

By the way: Google's MapReduce programming model (which is implemented by Apache Hadoop, for instance) builds upon the combination of map and reduce in a parallel computing environment.

Update: Added the section on array_filter() in response to a comment by René Leonhardt.

Defined tags for this entry: , , , ,

PHPUnit 3.2.14

Sebastian Bergmann » 19 February 2008 » in Announcements » 2 Comments

  • Added assertFileEquals() and assertFileNotEquals(). [2447]
  • Implemented the missing *AndWait commands of the SeleniumTestCase extension. [2464] [2468]
  • The error-to-exception conversion is now optional. [2477]
  • Implemented #387: Add --stop-on-failure to XML configuration file. [2443]
  • Fixed #384: assertEquals() does not print out custom message. [2400]
  • Fixed #388: $php_errormsg not set. [2439]
  • Fixed #394: Ignoring code blocks does not work. [2488]
  • The *AndWait commands of the SeleniumTestCase extension use sleep() instead of waitForPageToLoad() now. [2472]
Defined tags for this entry: ,

Workflow Engine Plugin System

Sebastian Bergmann » 19 February 2008 » in New Features » 3 Comments

eZ Components

Version 1.2 of the Workflow component that is part of the eZ Components introduces a plugin system that allows developers to hook into the workflow engine at well-defined extension points.

For now, plugin code can be called

  • after an execution has been started
  • after an execution has been suspended
  • after an execution has been resumed
  • after an execution has been cancelled
  • after an execution has successfully ended
  • before a node is activated
  • after a node has been activated
  • after a node has been executed
  • after a service object has been rolled back
  • after a new thread has been started
  • after a thread has ended
  • before a variable is set
  • after a variable has been set
  • before a variable is unset
  • after a variable has been unset

ezcWorkflowExecutionListenerPlugin and ezcWorkflowExecutionVisualizerPlugin are two workflow execution engine plugins that will ship with Workflow 1.2. The former is a refactored version of the execution logging code of Workflow versions 1.0-1.1.

The latter is new and can be used to visually log the execution of a workflow as shown below.

Execution of a workflow

The ezcWorkflowExecutionVisualizerPlugin generates a series of DOT files that can be rendered into single pictures using GraphViz. For the animation above, I crudely joined the single images to an animated GIF.

The before hooks are special as they allow the plugin to change (or even prevent) the current execution step. This will eventually allow for Aspect-Oriented Programming on the workflow level.

Defined tags for this entry: , , ,

PHPUnit 3.2.13

Sebastian Bergmann » 09 February 2008 » in Announcements » 0 Comments

  • Implemented #365: Directories and files not visually distinguishable in code coverage report. [2383]
  • Fixed #353: Incorrect error message in XmlDataSet.php. [2387]
  • Fixed #383: PgSQL.php missing in PEAR package. [2375]
Defined tags for this entry: ,

PHPUnit 3.2.12

Sebastian Bergmann » 07 February 2008 » in Announcements » 0 Comments

  • The XML logfile for Code Coverage information now contains namespace and package information. [2351]
  • Implemented #352: Add flag for "run completed" to Test Database's run table. [2364]
  • Implemented #357: Create a DbUnit metadata driver for PostgreSQL. [2306]
  • Implemented #361: Avoid warnings caused by @include usage. [2232]
  • Fixed #354: Error on delete records that have foreign keys. [2295]
  • Fixed #356: --log-xml causes a fatal error with empty test cases. [2223]
  • Fixed #367: Mock Object generation fails for methods of internal classes with optional arguments. [2359]
  • Fixed #372: never() gives wrong error message. [2368]
  • Fixed #374: Allow for real TRUNCATE calls in databases that support them. [2303]
  • Fixed #378: diff binary not found on Windows. [2326]
  • PHPUnit_Util_Class::getPackageInformation() is now namespace-aware. [2339] [2343]
Defined tags for this entry: ,