In order to use variables from the scope that the anonymous function came from, you have to explicitly import them into the anonymous function with the use[1] block:
public function getTotal($tax)
{
$total = 0.00;
$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
In other languages that have true closures, the anonymous function "closes over" the lexical scope in which it was declared.
I for one don't find it particularly shocking. While I agree it's not common, having things more explicit in PHP rather than less is not necessarily a bad thing. Of course, this being PHP, this is probably by accident. I've been bitten in the past in Perl and Javascript by thoughtless capture of variables from the outer scope.
Wrong. You only need to use the free variables of the closure, you don't need to copy the entire environment from the function you're defining your closure in. By the definition of a free variable you actually use it, otherwise it wouldn't be a free variable of the function! Python definitely does not work the same way, but in Python "x = 3" can inadvertently shadow (make a local name) something defined in the outer scope, but that's a completely different problem.
In modern versions of Python you can declare "nonlocal x", but that's only necessary if you want to assign to x. Since assignment in Python creates a local variable by default, there needs to be a way to tell the byte compiler not to shadow the nonlocal variable.
If you don't assign to x, the compiler will do the right thing without help.
[1]: http://www.php.net/manual/en/functions.anonymous.php