PHP gets lambda methods, closures

Not one month after I wrote about the future of PHP (June 2008), I was quite happily proven wrong.

For my part, I’d like to see first-class functions and closures included in the language. [...]

But none of that will happen, because PHP is a language in decline. Not a decline in usage—it will only continue to expand its reach—but in the addition of innovative features from other languages. There will be no need to evolve; most of the agitators for change will have moved on.
Me

It’s always been in my nature to own up to it when I’m proven wrong, so consider this my mea culpa. PHP has always been a klugey language, borrowing from other languages and implementing those ideas in somewhat endearingly clunky ways. I naively believed that that dynamism was coming to an end, but as you can see from the link above, that’s demonstrably not the case. Despite that, I still think there is a slow but steady “brain drain” from the ranks of the top tier of PHP developers—I’ve seen it first hand in the last few years and the overall trend should make PHP developers at least a little uncomfortable.

Anyway, the closure implementation coming in PHP 5.3 is, like namespaces, a little clunky.

function replace_in_array($search, $replacement, $array) {
    $map = function ($text) use ($search, $replacement) {
        if (strpos($text, $search) > 50) {
            return str_replace($search, $replacement, $text);
        }
        return $text;
    };
    return array_map($map, $array);
}

Yeah, you have to manually link the variables to make them available to the closure. Not ideal, but neither is having to manually specify your scope in JavaScript (via Function.apply()).

There are a few of other differences in PHP 5.3′s implementation of closures and other languages:

  • First, like other functions, they have access to the global scope with the global keyword. Do yourself a great big favor and just avoid doing that.
  • Second, you can choose which variables are linked by reference and which are not.
  • Finally, you can declare an anonymous function static if it’s declared in a class but doesn’t use an instance of that class for anything. If you have a large object, this would prevent the closure from retaining a reference to that instance (and therefore, its memory footprint) after it has outlived its usefulness. This will probably be the least understood aspect of PHP closures for most developers.

Currying is now possible as well. Ryan Timmons wasted no time in writing a method for doing just that:

function curry($function, $argument) {
    return function() use ($function, $argument) {
        $arguments = func_get_args();
        array_unshift($arguments, $argument);
        return call_user_func_array($function, $arguments);
    };
}

Between this, namespaces, late static binding, and a bundled packaging method (ext/phar), the next version of PHP is looking more like a major release instead of a minor one.

PHP 5.3 is scheduled for final release in October [update: it's been pushed back to the end of Q1 2009].

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

Tags: ,

2 comments

  1. Nice article. Thanks. :) Eugene

Leave a comment