note 97296 modified in functions.anonymous by danbrown

From: Date: Tue, 13 Apr 2010 02:42:31 +0000
Subject: note 97296 modified in functions.anonymous by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-168186@lists.php.net to get a copy of this message
In the code <?php function new_counter() { $counter = mt_rand(); return function()use(&$counter) { return ++$counter; }; } $t1 = new_counter(); $t2 = new_counter(); echo $t1(),"\n"; echo $t1(),"\n"; echo $t2(),"\n"; echo $t2(),"\n"; echo $t1(),"\n"; echo $t1(),"\n"; ?> The variable $counter is local to new_counter() and is used by reference by the returned lambda function. Because $counter is not static, a new variable is created each time new_counter() is called. But because the lambda function uses a REFERENCE to the $counter variable - and not a new local variable with a copy of the value $counter had when the lambda function was constructed - the $counter variable created when new_counter() ran still exists (because a reference to it still exists). Every lambda function has a variable reference "hardwired" into it. That variable therefore persists across calls to the lambda function - rather like a static variable. But that variable is only LOCAL to the new_counter() function that created it. As soon as new_counter() returns, it gives up its reference to $counter. When new_counter() is called again, it gets allocated a NEW $counter variable and gives a reference to THAT variable to the lambda function it constructs. So the lambda functions in $t1 and $t2 each have their OWN $counter variable - separate from the other's, which persists from one call to the next. The effect is very similar to declaring and initialising $counter as static within the lambda function - and then it doesn't need to use anything from new_counter() - but you can't initialise a static variable with a function call like mt_rand()! Pending a decision on what it should mean, $this is not currently (as of 5.3.2) usable within anonymous functions. There are roughly two positions (plus attempts at compromise), that can be called "early" and "late". Early: $this refers to the object in whose scope the anonymous function is constructed. <?php class Creator { public function make_anonymous() { return function() { return $this; }; } } class Caller { public $p; public function call_anonymous($f) { $this->p = $f(); } } $alpha = new Creator; $omega = new Caller; $omega->call_anonymous($alpha->create_anonymous()); // $omega->p === $alpha ?> Late: $this refers to the object in whose scope the anonymous function is called. <?php class Creator { public function make_anonymous() { return function() { return $this; }; } } class Caller { public $p; public function call_anonymous($f) { $this->p = $f(); } } $alpha = new Creator; $omega = new Caller; $omega->call_anonymous($alpha->create_anonymous()); // $omega->p === $omega ?> So until this is cleared up, $this won't work in an anonymous function. (Personally, I favour the early method; otherwise the anonymous function - and therefore its Creator - has access to all of the Caller's private properties.) --was-- In the code <?php function new_counter() { $counter = mt_rand(); return function()use(&$counter) { return ++$counter; }; } $t1 = new_counter(); $t2 = new_counter(); echo $t1(),"\n"; echo $t1(),"\n"; echo $t2(),"\n"; echo $t2(),"\n"; echo $t1(),"\n"; echo $t1(),"\n"; ?> The variable $counter is local to new_counter() and is used by reference by the returned lambda function. Because $counter is not static, a new variable is created each time new_counter() is called. But because the lambda function uses a REFERENCE to the $counter variable - and not a new local variable with a copy of the value $counter had when the lambda function was constructed - the $counter variable created when new_counter() ran still exists (because a reference to it still exists). Every lambda function has a variable reference "hardwired" into it. That variable therefore persists across calls to the lambda function - rather like a static variable. But that variable is only LOCAL to the new_counter() function that created it. As soon as new_counter() returns, it gives up its reference to $counter. When new_counter() is called again, it gets allocated a NEW $counter variable and gives a reference to THAT variable to the lambda function it constructs. So the lambda functions in $t1 and $t2 each have their OWN $counter variable - separate from the other's, which persists from one call to the next. The effect is very similar to declaring and initialising $counter as static within the lambda function - and then it doesn't need to use anything from new_counter() - but you can't initialise a static variable with a function call like mt_rand()! http://php.net/manual/en/functions.anonymous.php

« previous php.notes (#168186) next »