2

I have some simple example:

function func1(){
    return function (){
        return 1;
    };
}

but it's not clear for me how I can use that for my reason. It seems that func1() returns just the same that anonymous function does. But if I write like this:

echo func1();

...I get an error:

Catchable fatal error: Object of class Closure could not be converted to string in [file_name] on line [line]

I can get nothing except an closure object:

var_dump(func1());
---------------------
object(Closure)[1]

however I can't see a practical use of this. It always contains the same object no matter what an anonymous function returns - object(Closure)[1]. (I use php 5.3.3) Also I see no way to store a value that an anonymous function returns within func1(). As I see it is an closuer object anyway. But how to use it there and beyond?

srgg6701
  • 1,878
  • 6
  • 23
  • 37
  • 4
    *This* one isn't so useful, but others might be: `function make_adder($x) { return function($y) use($x) { return $x + $y; } }` lets you do something like `$adder = make_adder(3); echo $adder(2); // prints 5`. – Waleed Khan Aug 08 '13 at 17:46
  • 1
    The above example can be used for [currying](http://stackoverflow.com/questions/36314/what-is-currying) functions, which is exceptionally useful. – Orbling Aug 08 '13 at 17:50
  • 1
    Recommend you spend some time playing with a more functional language, that will give you a better feel for how to use functional programming. Then when you return to PHP, you will find the new closures, anonymous functions and the now more useful callback array functions, far more useful. – Orbling Aug 08 '13 at 17:55

2 Answers2

4

In your example, the return value of the call to func1 is a function (more specifically, a Closure). The error you're getting is due to php not being able to convert this object to a string. If you want to print the value returned by the closure, you need to call it.

function func1() {
    return function () {
        return 1;
    };
}

$f = func1(); // Create the closure
echo $f();    // Calls the closure

This example is simply a function returning a function and doesn't demonstrate what sets a closure apart from any other first class function, and that is that a closure can contain state unique to it's creation. In other words, you can generate functions from the same code that differ in the data they can access.

Consider this trivial example:

 function multiplier($m) {
     return function ($v) use ($m) {
         return $v * $m;
     };
 }

 $mult_5 = multiplier(5);
 echo $mult_5(5); // prints 25

 $mult_10 = multiplier(10);
 echo $mult_10(5); // prints 50

Again, this is a very trivial example, but it does demonstrate a couple of important things. First, we only defined a single function, yet by calling this function were able to generate two similar but different functions simply by changing the parameters when we called them. Also, consider that the function each have their own "state". In the case of the function I named $mult_5, it knows that its own internal $m value is 5, and that is different than the $m value of the $mult_10 function. The value for each of these was passed to the multiplier function and that function has completed, but the value lives on in the returned function/closure.

It's also worth noting that each return value of a call to multiplier is a first class function, meaning that you can write generalized functions (like multiplier) and then use them to generate more specific functions 'on-the-fly', functions which are more specifically appropriate to the current environment/state of your program.

If you are familiar with OOP, the above example could be easily re-written using OOP:

class Multiplier {

        protected $m;

        public function __construct($m) {
                $this->m = $m;
        }

        public function multiply($v) {
                return $v * $this->m;
        }
}

$mult_5 = new Multiplier(5);
echo $mult_5->multiply(5);  // prints 25

$mult_10 = new Multiplier(10);
echo $mult_10->multiply(5); // prints 50

... and, this is very subjective, but I much prefer the more consice syntax of the closure.

Alternatively, you could just use a more general function to begin with:

function multiplier($a, $b) {
    return $a * $b;
}

echo multiplier(5, 5);
echo multiplier(5, 10);

But the benefit of using a closure instead is that you can hide data (like the multiplier, in this example).

Carl Groner
  • 4,149
  • 1
  • 19
  • 20
  • Thank you, Carl for a brilliant answer! :) It really filled a gap in my understanding of the subject. Now I'm reading a pretty good book (that called Php.Pro.Programming), but this point was explained there rather poor :( May be you know some book better? – srgg6701 Aug 10 '13 at 06:46
1

Anonymous functions become useful when you use them as parameters for functions like array_filter(). See here documentation here.

Also, have tried doing this:

$x = func1();
echo $x();

If so you will the results do depend on how you define func1.

Annabel
  • 1,394
  • 14
  • 23
  • I think he's asking what is the practical use of closures, but he's not applying closure correctly. – Strawberry Aug 08 '13 at 18:01
  • To be honest, I don't have a Comp Sci degree and so don't understand closures, but I can still use them for use them for lots of useful stuff in PHP and with jQuery. – Annabel Aug 08 '13 at 18:14