【PHP】function use - 無名関数の親スコープ変数利用

【PHP】function use - 無名関数の親スコープ変数利用

ここでは、無名関数で親スコープの変数を利用する方法について解説します。

検証環境

親スコープの変数利用

無名関数で外部から値を与える方法は2つあります。

1つは引数を使う方法ですが、もう1つはuseキーワードを使う方法です。

useキーワードを使うことで、親スコープの変数を無名関数に与えることができます。

無名関数を引数に必要とする関数やメソッドは、無名関数の引数が決まっていることがあります。

そのような状況で、更に別の値を与えるにはuseキーワードを使った方法が有効です。

基本構文

function( 仮引数1, 仮引数2 ... ) use ( 親スコープの変数1, 親スコープの変数2 ... ) {
    処理
}

無名関数の定義においてuseを記述し、続く丸括弧(())内に親スコープの変数を指定します。

変数が複数ある場合は、カンマ(,)区切りで記述することが可能です。

サンプル

<?php

$z = 8;

___ih_hl_start
$addition = function( $x ) use ( $z ) {
___ih_hl_end
    return $x . " + " . $z . " = " . ( $x + $z );
};

echo $addition(3)."\n";

?>
$ php sample.php
3 + 8 = 11

5行目のuse ( $z )が親スコープの変数利用の定義です。

この記述によって、無名関数の処理で$zを使えるようになり、実行結果から親スコープと同じ値を引き継いでいることが分かります。

値について

useキーワードで与えた変数は、無名関数を定義した時の値を記憶します。

そのため、定義後に対象変数の値を変更しても、無名関数の処理に影響はありません。

実際に上記サンプルの無名関数の定義後に$zの値を変更しても実行結果は同じです。

<?php

$z = 8;

$addition = function( $x ) use ( $z ) {
    return $x . " + " . $z . " = " . ( $x + $z );
};

___ih_diff_start
+$z = 100;
___ih_diff_end

echo $addition(3)."\n";

?>
$ php sample.php
3 + 8 = 11

無名関数の$zは親スコープの$zの値渡しなので、複製的な扱いとなり、このような結果になります。

同じ値を扱いたい場合は、参照渡しを使います。

<?php

$z = 8;

___ih_diff_start
-$addition = function( $x ) use ( $z ) {
+$addition = function( $x ) use ( &$z ) {
___ih_diff_end
    return $x . " + " . $z . " = " . ( $x + $z );
};

+$z = 100;

echo $addition(3)."\n";

?>
$ php sample.php
103

5行目の$zを参照渡しに変更しました。

これにより、親スコープの$zと同じ記憶領域を扱うため、無名関数の定義後でも値の変更の影響を受けるようになります。

ただし、参照渡しは受け取り側(ここでは無名関数)での値の変更が、与えた側にも影響することに注意してください。

演習問題

問題1

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

  • 合計金額の計算式は『単価×個数+消費税』とする
  • 単価と個数は標準入力で与える
  • 消費税の税率は10%とする
  • 合計金額を計算する処理は無名関数で行う(変数に記憶しておく)
  • 消費税率は無名関数にuseキーワードで与える
$ php practice.php
単価 > 100
個数 > 5
合計料金 : 550円
$ php practice.php
単価 > 1800
個数 > 7
合計料金 : 13860円

問題2

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

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