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.)

4

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

5 Comments

But since anonymous functions are immutable, isn't it true to say that the engine should have had optimized this for us?
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.
PHP requires you to declare external variables that should be referenced in the closure with the use (<vars>) declaration. The parser can easily tell that the function doesn't have this option, so all of them are the same.
@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?
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. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.