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

kaila355-300x200再帰のサンプルと言えば、フィボナッチ。
The Lazy Rule of Thirds | Jake Garn Photography

ってことで PHP Advent Calendar jp 2010 16日目おしまい。
明日は koyhoge さんです。

コメント

  • twitter 2011年12月25日 日曜日 4:40 PM

    “匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp” http://t.co/sMXDU7cR

    kanno_kanno
  • twitter 2011年4月1日 金曜日 3:45 PM

    無名関数を使った再起処理でecho $fib(10)が55になる感覚がつかめない。。。 http://dogmap.jp/2010/12/16/php-advent-calendar-2010-day-16/ #php

  • twitter 2010年12月17日 金曜日 11:46 AM

    匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://ff.im/-vmUhE

  • hatena bookmark 2010年12月16日 木曜日 5:44 PM

    「匿名」関数はじつは名前がある。へー

  • hatena bookmark 2010年12月16日 木曜日 1:13 PM

    」無名関数の実体は Closure オブジェクトですが、匿名関数の実体は "\0lambda_1" と言う名前の関数なのです。」

  • twitter 2010年12月16日 木曜日 1:13 PM

    」無名関数の実体は Closure オブジェクトですが、匿名関数の実体は "\0lambda_1" と言う名前の関数なのです。」 / 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.… http://htn.to/PCq5dE

  • hatena bookmark 2010年12月16日 木曜日 1:08 PM

    PHP5.3の無名関数でクロージャ、function() use (&$var)

  • hatena bookmark 2010年12月16日 木曜日 1:04 PM

    匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp

  • twitter 2010年12月16日 木曜日 12:44 PM

    匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://dlvr.it/BTdh7

  • twitter 2010年12月16日 木曜日 12:34 PM

    匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://htn.to/e3G9oL

  • twitter 2010年12月16日 木曜日 12:26 PM

    匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp
    http://ow.ly/3pZth ここらへんもりもり使えると楽しいだろうなー。借りてるサーバはいまだにPHP4ですけど。

  • twitter 2010年12月16日 木曜日 12:15 PM

    匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://bit.ly/fCM8Fm

  • twitter 2010年12月16日 木曜日 12:07 PM

    匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://dlvr.it/BTYbM

  • twitter 2010年12月16日 木曜日 12:01 PM

    へぇ。なるほど。 / 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://htn.to/pqC2Dy

  • hatena bookmark 2010年12月16日 木曜日 12:01 PM

    へぇ。なるほど。

  • twitter 2010年12月16日 木曜日 11:54 AM

    RT @shin1x1: #phpadvent2010 簡潔で分かりやすい良いまとめ / 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://htn.to/5wc66U

  • twitter 2010年12月16日 木曜日 11:37 AM

    [h] 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://bit.ly/hdFnL1

  • hatena bookmark 2010年12月16日 木曜日 11:28 AM

    5.3

  • hatena bookmark 2010年12月16日 木曜日 11:06 AM

    #phpadvent2010 簡潔で分かりやすい良いまとめ

  • twitter 2010年12月16日 木曜日 11:06 AM

    #phpadvent2010 簡潔で分かりやすい良いまとめ / 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) : dogmap.jp http://htn.to/5wc66U

  • delicious 2010年12月16日 木曜日 9:55 AM

    "PHP5.3から無名関数が利用できるようになりました/無名関数では、use を使って親のスコープから変数を引き継ぐことができます。"

  • twitter 2010年12月16日 木曜日 12:21 AM

    RT @wokamoto: 書きましたー。 – 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目) http://dogmap.jp/CZ #phpadvent2010

コメントする

入力いただいたメールアドレスから Gravatar に登録されているアイコンを表示します。
(メールアドレスは公開されません)

改行と段落タグは自動で挿入されます。メールアドレスは表示されません。

:mrgreen: :-P :-D :-) ;-) :-o :-| :-( 8-O :-? 8-) :twisted: :evil: :oops: :roll: :cry: :lol: :-x more »