【PHP】無名関数(クロージャー) - 名前のない関数(Closure)

【PHP】無名関数(クロージャー) - 名前のない関数(Closure)

PHPには無名関数と呼ぶ、“名前のない関数”があります。

ここでは無名関数について解説します。

検証環境

無名関数

無名関数は“名前のない関数”です。

別名でクロージャーとも呼ばれ、関数のように定義できますが、実態はPHPに標準で用意されたClosureクラスのオブジェクトです。

オブジェクトのため、関数を変数に代入したり、引数として与えることができます。

無名関数の定義

無名関数を使用するには定義が必要です。

基本構文

function( 仮引数1, 仮引数2 ... ) {
    処理
}

基本的には関数と同じ構文ですが、関数名は記述しません。

また、Closureクラスのオブジェクトのため、変数に代入することが可能です。

変数 = function( 仮引数1, 仮引数2 ... ) {
    処理
}

サンプル

<?php

___ih_hl_start
$addition = function( $x, $y ) {
    return $x + $y;
};
___ih_hl_end

?>
$ php sample.php
$

3〜5行目が無名関数の定義です。

代入演算子で$additionに無名関数を記憶しています。

無名関数は通常の関数と異なり、ブロック({})の最後にセミコロン(;)が必要です。

無名関数の呼び出し

無名関数を記憶する変数を使って呼び出す方法です。

基本構文

変数( 実引数1, 実引数2 ... )

関数の呼び出しの構文において、関数名の部分に無名関数を記憶する変数を記述します。

サンプル

<?php

$addition = function( $x, $y ) {
    return $x + $y;
};

___ih_hl_start
echo $addition(3, 5)."\n";
___ih_hl_end

?>
$ php sample.php
8

7行目の$addition(3, 5)が無名関数の呼び出しです。

実行結果からも正常に処理されたことが分かります。

実引数の利用

無名関数は実引数として与えることが可能です。

<?php

function calculation( $a, $b, $closure ) {
    ___ih_hl_start
    return $closure($a, $b);
    ___ih_hl_end
}

___ih_hl_start
$result1 = calculation(5, 7, function( $x, $y ) {
    return $x + $y;
});
___ih_hl_end

___ih_hl_start
$result2 = calculation(5, 7, function( $x, $y ) {
    return $x - $y;
});
___ih_hl_end

echo "result1 = ".$result1."\n";
echo "result2 = ".$result2."\n";

?>
$ php sample.php
result1 = 12
result2 = -2

calculation関数は第3引数($closure)に無名関数を受け取り、その無名関数を呼び出します。

7行目と11行目のcalculation関数の呼び出しで、第3引数に無名関数を与えており、実行結果から各無名関数の内容に従った計算が行われたことが分かります。

直接的な呼び出し

無名関数はvar_dump関数の引数に与えて情報を出力すると、Closureクラスのオブジェクトであることが分かります。

<?php

var_dump(function( $x, $y ) {
    return $x + $y;
});

?>
$ php sample.php
object(Closure)#1 (1) {
  ["parameter"]=>
  array(2) {
    ["$x"]=>
    string(10) ""
    ["$y"]=>
    string(10) ""
  }
}

無名関数の定義はClosureクラスのオブジェクトを生成することに同じであるため、変数に記憶しなくても直接呼び出すことが可能です。

<?php

echo (function( $x, $y ) {
    return $x + $y;
})(3, 8);

?>
$ php sample.php
11

この記法は変数に記憶しないため、呼び出し後に再度同じオブジェクトにアクセスできません。

そのため、単発的に利用する無名関数の記法になります。

一般的には変数に記憶して利用することが多いですが、このような記法があることを覚えておくと、他者が開発したコードを読む手助けとなります。

演習問題

問題1

会計の合計金額を計算するプログラムを作成してください。
なお、下記条件を満たすものとします。

  • 合計金額の計算式は『単価×個数』とする
  • 単価と個数は標準入力で与える
  • 合計金額を計算する処理は無名関数で行う(変数に記憶しておく)
$ php practice.php
単価 > 100
個数 > 5 
合計料金 : 500円
$ php practice.php
単価 > 1800
個数 > 7
合計料金 : 12600円

問題2

複数数値の一覧と合計値を出力するプログラムを作成してください。
なお、下記条件を満たすものとします。

  • 複数数値は標準入力で与える(空文字が入力されるまで)
  • 複数数値の一覧を出力する処理を行う無名関数を作成する
  • 複数数値の合計値を戻り値として返す処理を行う無名関数を作成する
  • execute関数を下記の次の仕様で作成する
    引数: 複数数値、クロージャー
    処理: クロージャーを呼び出し、引数に複数数値を与える
$ php practice.php
===  Input  ===
> 123
> 456
> 789
> 
=== Closure ===
123
456
789
total : 1368
$ php practice.php
===  Input  ===
> 1234
> 3456
> 5678
> 7890
> 
=== Closure ===
1234
3456
5678
7890
total : 18258