今回はPHPのクロージャについてです。
PHP 5.3から PHPはクロージャが使えるようになりましたが、
use節の使い方によって、参照を束縛するか値を束縛するかが変わります。
例を見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?php $inc = function() { $cnt = 1; return function() use ($cnt){ return $cnt++; }; }; $ref_inc = function() { $cnt = 1; return function() use (&$cnt){ return $cnt++; }; }; $counter = $inc(); $ref_counter = $ref_inc(); echo "counter:" . $counter() . "\n"; echo "counter:" . $counter() . "\n"; echo "counter:" . $counter() . "\n"; echo "ref_counter:" . $ref_counter() . "\n"; echo "ref_counter:" . $ref_counter() . "\n"; echo "ref_counter:" . $ref_counter() . "\n"; ?> |
1 2 3 4 5 6 7 |
$php test_closure.php counter:1 counter:1 counter:1 ref_counter:1 ref_counter:2 ref_counter:3 |
use節に&をつけて参照渡しを行うと、
クロージャオブジェクトは参照に対して捕捉するため、
参照先についてはミュータブルになります。
つまり参照については、イミュータブルですが、
参照の示す先についてはクロージャオブジェクトは関知しないということです。
対して、use節に&をつけないと、クロージャオブジェクトは値に対して捕捉するため
イミュータブルになり、値の更新が行われません。
PHPはどこで参照渡しが行われ、どこで値渡しが行われるかわかりにくいので、
この辺りは注意したいですね。