September, 2008


26
Sep 08

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!

3
Sep 08

Zend_Paginator

On and off for the last two or three months, Jurriën Stutterheim and I wrote Zend_Paginator, the pagination component for Zend Framework. Yesterday it was officially released as part of Zend Framework 1.6.

This was our first contribution to the framework, and was very much a collaborative working relationship. I first created a proposal in about half an hour on Christmas Eve 2007 for how I thought a pagination component should work after being dissatisfied with existing solutions. It contained some good ideas about flexibility, but on its own it was half an idea, at best. So I promptly forgot about it.

Then Jurriën came along and created a proposal based on his Zym_Paginate component, which was part of Zym Framework, itself an extension of Zend Framework.

At the urging of Zend, we merged our proposals. We refined our ideas, incorporating aspects from each of our proposals in addition to brand new thoughts. Then I wrote a new component from scratch based in part on Jurriën’s existing work. He wrote the excellent unit tests (with 100% code coverage, not always easy to achieve!), and I wrote the DocBook documentation. I also can’t overstate the positive impact the community had, particularly from Bryce Lohr who prompted us to decouple and reorganize major portions of the component.

Anyway, I’m very happy with how it turned out. There are still a few issues, most of them minor—and because of the component’s flexible design, there are almost always workarounds. They should be fixed in time for 1.6.1.

Here’s some praise for the component:

Upcoming Zend_Paginator in 1.6 is absolutely brilliant. Wasted time be gone.
Joakim Nygård

The new Zend Framework 1.6 release candidate includes a Zend_Paginator class, which is an excellent thing to have around because I know I’ve re-invented that wheel on every site I’ve developed. My only criticism of the new Zend_Paginator is it offers a daunting amount of possibilities.
Chris Beer

This really is a beautifully crafted component, very elegant, very classy.
—David Mintz, via e-mail

I’ve seen dozens of different paginators in the last couple of years, and to be honest, this one is by far the best. You got everything right! I can’t wait for this component to hit the incubator.

It’s great, well done guys.
Federico Cargnelutti

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!