shin1x1 さんから、開始された PHP Advent Calendar jp 2010 16日目です。
書くTipsは、10分で考えて、5分で書ける内容で ok です。
とのことなので、さらっと。
PHP5.3から導入された無名関数って、5.2以前からある匿名関数とどうちがうの?ってお話。
PHP5.3から無名関数が利用できるようになりました。こんな感じで書けます。
$closure_echo = function( $s ){
echo $s . "\n";
};
$closure_echo('Hello World!');
preg_replace_callback なんかの第2引数に使う一時的な関数を定義するのに便利ですね。
PHP5.2までは、同様のことを create_function を使って、実現してました。
$anonymous_echo = create_function( '$s', 'echo $s."\n";' );
$anonymous_echo('Hello World!');
第1引数にパラメータを、第2引数に関数のコードを、それぞれ文字列として渡す必要があります。
コーディングしづらいこと、この上ないですね。
さて実際には、この無名関数と匿名関数は、どう違うのでしょう?
それぞれに割り当てられた変数を var_dump() してみるとわかります。
無名関数
var_dump($closure_echo);
↓
object(Closure)#1 (1) {
["parameter"]=>
array(1) {
["$s"]=>
string(10) "<required>"
}
}
匿名関数
var_dump($anonymous_echo); ↓ string(9) "lambda_1"
無名関数の実体は Closure オブジェクトですが、匿名関数の実体は "\0lambda_1" と言う名前の関数なのです。
ちなみに匿名関数を複数定義すると、lambda_1, lambda_2, lambda_3… という風に連番で関数名が付けられていきます。
なので、匿名関数は作成した後に function_exists() 関数で存在を確認することもできます。
$anonymous_echo = create_function('$s', 'echo $s."\n";');
if (function_exists("\0lambda_1")) {
$anonymous_echo('Hello World!');
}
しかも、この匿名関数を割り当てた変数を unset しても、関数定義自体は残ってるので call_user_func で呼び出すことも可能です。
$anonymous_echo = create_function('$s', 'echo $s."\n";');
unset($anonymous_echo);
if (is_callable("\0lambda_1")) {
call_user_func("\0lambda_1", ''Hello World!'');
}
もちろん、無名関数は実体が Closure オブジェクトなんで、こんなハレンチなことはできません。
他に違いはあるでしょうか?
無名関数では、use を使って親のスコープから変数を引き継ぐことができます。
$count = 0;
$closure = function() use ( &$count ) {
echo $count++ . "\n";
};
$closure();
$closure();
$closure();
↓
0 1 2
もちろん use を使って自分自身を渡せば再帰処理もできます。
$fib = function( $n ) use( &$fib ) {
if ( $n < 2 ) {
return $n;
} else {
return $fib( $n -1 ) + $fib( $n -2 );
}
};
echo $fib(10);
再帰のサンプルと言えば、フィボナッチ。
The Lazy Rule of Thirds | Jake Garn Photography
ってことで PHP Advent Calendar jp 2010 16日目おしまい。
明日は koyhoge さんです。





“匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp” http://t.co/sMXDU7cR
無名関数を使った再起処理でecho $fib(10)が55になる感覚がつかめない。。。 http://dogmap.jp/2010/12/16/php-advent-calendar-2010-day-16/ #php
匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://ff.im/-vmUhE
「匿名」関数はじつは名前がある。へー
」無名関数の実体は Closure オブジェクトですが、匿名関数の実体は "\0lambda_1" と言う名前の関数なのです。」
」無名関数の実体は Closure オブジェクトですが、匿名関数の実体は "\0lambda_1" と言う名前の関数なのです。」 / 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.… http://htn.to/PCq5dE
PHP5.3の無名関数でクロージャ、function() use (&$var)
匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp
匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://dlvr.it/BTdh7
匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://htn.to/e3G9oL
匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp
http://ow.ly/3pZth ここらへんもりもり使えると楽しいだろうなー。借りてるサーバはいまだにPHP4ですけど。
匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://bit.ly/fCM8Fm
匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://dlvr.it/BTYbM
へぇ。なるほど。 / 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://htn.to/pqC2Dy
へぇ。なるほど。
RT @shin1x1: #phpadvent2010 簡潔で分かりやすい良いまとめ / 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://htn.to/5wc66U
[h] 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://bit.ly/hdFnL1
5.3
#phpadvent2010 簡潔で分かりやすい良いまとめ
#phpadvent2010 簡潔で分かりやすい良いまとめ / 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://htn.to/5wc66U
"PHP5.3から無名関数が利用できるようになりました/無名関数では、use を使って親のスコープから変数を引き継ぐことができます。"
RT @wokamoto: 書きましたー。 – 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) http://dogmap.jp/CZ #phpadvent2010