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.
$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:
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].