無名関数(クロージャ)とビルトイン関数

無名関数(クロージャ)

無名関数は親のスコープから変数を継承しますが、その継承にはuseを使います。useを使わず、呼び出し側で指定した値を使いたい場合は「($a,$b)」などとし、両方の引数の数を一致させます。useを使った場合、局所的にのみ有効になるレキシカル変数を引数として指定します。クロージャは変数の値として使えますが、クロージャの記述があると内部的にはビルトインのClosureクラスが呼び出されてインスタンスに変換されています。このクラスは無名関数を表すために用意されたものでPHP5.3から使えるようになった機能です。無名関数の末尾の「}」は「};」としなければ動作しませんが、組み込み関数のコールバックでは使いません。

PHP
1
2
3
4
5
6
7
8
9
10
11
<?php
// 無名関数を変数に代入して使った場合
$b=5;
// 左側の引数である「$a」が呼び出し元から渡される変数です。
// 右側の引数である「$b」がレキシカル変数です。
$c=function($a) use ($b){
return $a+1;
};
// 通常の関数名と異なり、変数名が無名関数を呼び出すための名前になります。
echo $c(5);
?>
実行結果:6

組み込み関数の引数にコールバック関数として無名関数を使用する

組み込み関数とは各プログラミング言語で最初から用意されている関数のことを言います。

array_map()

array_map()は指定した配列のキーに対する値にコールバック関数を適用して使う組み込み関数です。

PHP
1
2
3
4
5
6
7
<?php
$a=array(1,2,3);
$c = array_map(function ($a){return $a+1;},$a);
foreach($c as $val){
echo $val;
}
?>
実行結果:234

array_mapでuseを使ったコールバック

PHP
1
2
3
4
5
6
7
8
<?php
$a=array(1,2,3);
$b=5;
$c = array_map(function ($d)use($b){return $d+$b;},$a);
foreach($c as $val){
echo $val;
}
?>
実行結果:678

array_walkでuseを使ったコールバック

array_walk()は配列の全てのキーに対する値にユーザー定義関数を適用する組み込み関数です。

PHP
1
2
3
4
5
<?php
$a=array(1,2,3);
$b=5;
array_walk($a, function ($c) use ($b){echo $c+$b.'。';});
?>
実行結果:6。7。8。

preg_replace_callback

preg_replace_callback()は正規表現検索を行い、コールバック関数を使用して置換を行います。配列であれば配列を返し、それ以外は文字列を返します。preg_replace()との違いは書式での置換後の部分が、この関数ではコールバックの指定になるところと、preg_replace()では複数パターンをまとめて記述できますが、この関数ではまとめて置換えることが出来ない点です。

PHP
1
2
3
4
5
6
<?php
$a = 'PHPのPHPによるPHPのための組み込み定義関数';
// パターンの「PHP」と「組み込み」が「ユーザー」に置き換えられます。
$pattern = '/PHP|組み込み/';
echo preg_replace_callback($pattern, function(){return "ユーザー";}, $a);
?>
実行結果:ユーザーのユーザーによるユーザーのためのユーザー定義関数

preg_replace_callback

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$a = '米100ドルと米200ドルと米300ドル';
// パターンキャプチャの「(米)(\d+)(ドル)」はそれぞれ、
// $matches[1]、$matches[2]、$matches[3]で取得できます。
// $matches[0]には、(米\d+ドル)の三つがまとめて入り、取得できます。
$pattern = '/(米)(\d+)(ドル)/';
echo preg_replace_callback(
$pattern,
function($matches){
print_r($matches);
$matches=$matches[2]*10;
// ここで米を日本、ドルを円に置き換えています。
return '日本'.$matches.'円';
},
$a
);
?>
実行結果:Array
(
[0] => 米100ドル
[1] => 米
[2] => 100
[3] => ドル
)
Array
(
[0] => 米200ドル
[1] => 米
[2] => 200
[3] => ドル
)
Array
(
[0] => 米300ドル
[1] => 米
[2] => 300
[3] => ドル
)
日本1000円と日本2000円と日本3000円

preg_replace_callback_array

preg_replace_callback_array()は正規表現検索を行い、コールバック関数を使って置き換えます。preg_replace_callback()との違いは、パターン単位で処理できる点です。preg_replace_callback()ではパターン文字列と対になる置き換え後の「|」(or)の処理がうまくできず、配列に入った「()」でキャプチャした値を非表示にするなどしてややこしい制御をしなければならないようです。この関数では配列の中のキー(パターン)に対する値に直接無名関数を記述することで「|」(or)と同様の処理ができます。

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$a = '米100ドルと米200ドルと米300ドル';
$a = preg_replace_callback_array(
[
// $aで出現する「米」を$match[0]で三つ取得。returnで「JP」に置換。
"/米/" => function ($match) {return "JP"; },
// $aで出現する「数字」を$match[0]で三つ取得。returnで取得した値に10をかけて置換。
"/\d+/" => function ($match) { return $match[0]*10; },
// $aで出現する「ドル」を$match[0]で三つ取得。$match[0]に「円を代入してreturnで返す。
"/ドル/" => function ($match) {$match[0]="円"; return $match[0]; },
], $a);
print_r($a);
?>

実行結果:JP1000円とJP2000円とJP3000円