Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Functional PHP 5.3 - What are Anonymous Functions and Closures? (recessframework.org)
25 points by KrisJordan on Aug 18, 2009 | hide | past | favorite | 17 comments


Good tutorial. A more practical application would have enhanced the article. Closures in PHP, just forget them!

As a byline, it is posted at recessframework. I did not know about the framework. Downloaded it gave it a spin and was impressed!


> As a byline, it is posted at recessframework. I did not know about the framework.

Ah thanks for that! I remember the guy posted a link here when Recess was in it's infancy. I gave it a spin but preferred more mature offerings :)

Time to give it another go I think.


This should be a big help in writing clean server-side sorts by an arbitrary column in tabular data.

Previously we've had to do some rather ugly things with "create_function" and lots of escaping in order to make arbitrary sort comparator functions.

An example of the old style:

    private function makeCompare($field, $desc) {
        return create_function('$a,$b', "
            \$r = strcasecmp(\$a['$field'], \$b['$field']);
            return " . ($desc ? '-1' : '1') . " * \$r;");
    }
Not my proudest moment, to be sure.


Nice article, but it still doesn't answer the question I've always had about anonymous functions: why are they more "important" (read: why is everyone making such a big deal about them) than pointers-to-functions in C? I've written C/C++ code that pass functions as arguments to other functions by using pointers. I could just as easily write code that returns a pointer to a function. The only difference I see here is that anonymous functions are, well, anonymous.

So someone clarify for me why this is any better. What am I missing?


This isn't necessarily any better, it just has more syntax support. However, it isn't equivalent to a function ptr, it's more equivalent to a structure with a fptr and associated data. A C++ function object or a C fptr pointing to a trampoline fn has exactly this functionality.

However, the functionality isn't the only thing. There are two notational conveniences that typically come along for the ride:

1) You can declare the function nested within another function. This is a necessary prerequisite to...

2) The associated structure is automatically created by the compiler based on what data the function uses in the surrounding context.

3) Just like the struct/fptr pair you might have created manually on the heap, you can return this function from another function with the data it captured coming along for the ride. That's generally were all the fun stuff happens :-)

To clarify this: See the recent "lambda" proposal for C++0x to see that same feature in the context of a Cish language, with the attendant modifications for manual memory management, stack based capture, etc.


The interresting part is that you can define on the spot a single usen, throwaway function to be used as a parameter of a function that accepts functions as arguments.

Another property of lambdas is nested defines with the possibility to return an inner function (be it anonymous or not) from an outer one.

At last their lexical scope allows, in the inner/outer functions described above, to keep the scope of the outer function alive as long as the returned inner function is referenced. This allows to make them work as lightweight objects (or even to define an object system if you want to).


Pointers can break easily. It's entirely possible to add or subtract from a pointer, which drops you in a different memory area. This isn't possible with anonymous functions, making them more safe.

It's the same with references vs. pointers. You can't do any calculations with references, but you can with pointers.


Not much. The other difference is that closures can access the local variables that are in scope at the point where the function is defined. I guess you could hack this together in C by packing and unpacking the variables into a struct together with the function pointer. It's a bit long winded that way though.

In smalltalk and ruby closures are used extensively to define new control structures using the block syntax.


It's functionally the same.


Anonymous first-class functions in PHP? I can't say that was high on my list of things I would classify as necessary to make it usable.


Before you had to write:

  function is_not_numeric($num){
    !is_numeric($num);
  }

  array_map('is_not_numeric', array(1,3,5,'a','c',3));
The fact that php used to take a string as the callback and not an expression is seriously broken.

Now (presumably), one can write:

  array_map(function($x){ !is_numeric($x) }, array(1,3,5,'a','c',3));
Although, ideally it would be:

  array_map(!is_numeric, array(1,3,5,'a','c',3));


Right, I'm not arguing that anonymous first-class functions are useful, I'm just saying that I think there are so many other things that are seriously broken with PHP as to make this akin to worrying about having enough clean forks for a dinner party while your house is on fire.

I'm not just PHP-trolling here, either. There is a history in the PHP project of adding features to the language without any reference to how they will be made "safe". The PHP interpreter is notoriously unhelpful at catching even the simplest of bugs. This just seems like another ad-hoc feature added to the list of things that are likely to introduce subtle bugs that are undetectable until they are running on a production system somewhere.


Seriously. Anonymous functions without a sane lexical system is asking for trouble, though marking closure variables will mitigate the problems a little.

I agree that PHP's house is on fire, but PHP has such a big house that I'm not sure it's noticed yet.


It's on my list! If we're doing a feature comparison of web scripting languages it was obviously lacking from PHP and present in one form or another in everything else. Not sure about the use syntax but at least it makes it clear what variables are closed over.


The use syntax is a little weird at first but it turns out to be straightforward to understand. In fact, being explicit about what is being closed over makes the function itself easier to understand.

PHP, being the quirky language that it is, needs the use syntax to enable closures for cases where there are dynamic variable references. This is a bad example but illustrates the problem:

$foo = 'bar'; $fun = function() use ($foo) { $var = 'foo'; echo ${$var}; }; $fun(); // output 'bar'

$fun = function() { $var = 'foo'; echo ${$var}; }; $fun(); // fails

Sure, you could close over the entire local namespace but that's an efficiency nightmare and leads to unpredictable code.


"intents and purposes"


Fixed. Thanks.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: