5

I have an array which stores multiple references to a single anonymous function:

$fns = array();
//some code
$fn = function(){
    echo 'this is closure 12345... < 67890';
    // etc etc..
};
for($x=12345; $x<67890; ++$x){
    $fns[$x] = $fn;
}

As can be seen, we're creating only one anonymous function.

What if we put the function declaration inside of the loop? :

$fns = array();
//some code
for($x=12345; $x<67890; ++$x){
    $fns[$x] = function(){
        echo 'this is closure 12345... < 67890';
        // etc etc..
    };
}

Is the engine smart enough to recognize that only one object needs to be created?

Does the above code create only one object or does it create one object per iteration?

(Question is targeted at both HHVM and Zend Engine.)

Pacerier
  • 86,231
  • 106
  • 366
  • 634
  • Did you profile it? 300 objects is nothing. You will likely not even be able to measure the difference with that few objects. Unless you start to create millions of objects, the difference is negligible. – Gordon Aug 05 '13 at 06:16
  • @Gordon http://stackoverflow.com/questions/239136/fastest-way-to-convert-string-to-integer-in-php#comment-4932053 – Pacerier Aug 05 '13 at 06:28
  • http://c2.com/cgi/wiki?PrematureOptimization – Gordon Aug 05 '13 at 06:37
  • @Gordon, We'd hardly find a coder not quoting http://c2.com/cgi/wiki?PrematureOptimization . And that's why we have http://stackoverflow.com/questions/239136/fastest-way-to-convert-string-to-integer-in-php#comment-4932053 in response to http://c2.com/cgi/wiki?PrematureOptimization . – Pacerier Feb 16 '15 at 04:33

1 Answers1

5

If you create the function inside the loop, you're creating 300 individual anonymous function objects. PHP does not optimize this away, since maybe that's what you want. That's a lot less efficient than creating the function once before the loop.

Here's the proof that two independent objects get created: http://3v4l.org/f3cdE

deceze
  • 510,633
  • 85
  • 743
  • 889
  • But since anonymous functions are immutable, isn't it true to say that the engine *should* have had optimized this for us? – Pacerier Aug 05 '13 at 05:56
  • 2
    For that PHP would first have to analyze whether the functions are exactly the *same*. Immutabity is not the issue, *sameness* is. If you included some external variables in the closure, that'd get hard to tell. And either way, PHP *doesn't*, regardless of whether it *should*. PHP pretty much does what you tell it to; this is not a highly abstract language like Haskell. – deceze Aug 05 '13 at 05:59
  • 4
    PHP requires you to declare external variables that should be referenced in the closure with the `use ()` declaration. The parser can easily tell that the function doesn't have this option, so all of them are the same. – Barmar Aug 05 '13 at 06:02
  • @deceze, ok. But still, of course they would be the same wouldn't it. How *could* they be different? Even with external variables like function()use($e){echo $e;} the $e is already binded when the function is created and if the $e was the same value, the function had to exactly identical isn't it? – Pacerier Aug 05 '13 at 06:07
  • 1
    Sure, I'm just saying you're expecting too much of the PHP compiler. Never have I written PHP code and thought *"oh don't worry about performance because PHP will optimize this into what-I-mean instead of what-I-wrote..."* Because PHP doesn't. :) – deceze Aug 05 '13 at 06:09