いろいろな関数呼び出し
再帰関数
自分自身を呼び出す関数。
<?php function factorial(int $sum): int { if ($sum !== 0) { return $sum * factorial($sum - 1); // factorial(n), factorial(n-1), ...と順次呼び出され、factorial(0)が呼び出されたときにループが終了する } return 1; // 再帰の終了点 } print factorial(5); // 120 = 5! ?>
可変関数
$変数名()で呼び出せる関数。変数名に応じて対応する関数を検索・実行できる。
<?php function area(int $height, int $width): int { return $height * $width; } $name = 'area'; $area = $name(4,5); print $area; // 20 // 変数$nameには'area'がセットされているので、可変関数$name(4,5)は$nameの部分が評価された結果、'area(4,5)'と同じ意味になる ?>
高階関数の実装
可変関数を利用して、汎用性の高い高階関数を設計できる。高階関数によって、共通機能はそのままに、個別の処理内容だけを自由に差し替えられる
<?php // 高階関数 // 枠組みとなる機能をだけを持ち、詳細な機能は関数の利用者が決める(可変関数$func()を自由に差し替える) function higherOrder(array $array, callable $func): void { // callable:コールバック関数(呼び出し先の関数で呼び出される関数) foreach ($array as $key => $value) { $func($value, $key); } } function showItem($value,$key): void { print "{$key}:{$value}\t"; } $result = 0; function total($value,$key): void { global $result; $result += $value; } $data = ['apple', 'banana', 'mango']; higherOrder($data, 'showItem'); => 0:apple 1:banana 2:mango // higherOrder()の仮変数$funcに'showItem'がセットされる // 配列の要素ごとにshowItem($data[n], n)が呼び出される $num = [2,3,5,12]; higherOrder($num, 'total'); print $result; => 22 // 別の関数名を$funcにセット ?>
- 高階関数higherOrder($array, $func)に任意の配列とコールバック関数名を渡して呼び出す
- 関数名が仮変数$funcにセットされる
- 配列の要素ごとに、任意の機能を持つ可変関数$funcが呼び出される
無名関数
↑の高階関数の呼び出しを無名関数で書き換えた例。
<?php higherOrder($data, function($value,$key): void { print "{$key}:{$value}\t"; } ); ?>
関数名が不要で機能だけが必要な場合、無名関数を利用することでコードの可読性が上がる。
use命令
use(変数名)で、親スコープの変数を利用できるようになる。
<?php $result = 0; higherOrder($num, function($value,$key) use(&$result) { // 無名関数の中で$resultに加算結果を書き戻す必要があるため、参照渡し $result += $value; } ); ?>
このコードでは$resultはグローバル変数なのでglobal命令でも代替可能だが、常にそうとは限らないので「親スコープから変数を引き継ぐ」という目的においてはuse命令がベター。
アロー関数
無名関数が単一の式しか持たないとき、アロー関数で記述できる。
<?php higherOrder($data, fn($value,$key) => print "{$key}:{$value}\t"; ); ?>
ちなみに、アロー関数の任意の式の中では親スコープの変数を暗黙的に利用できる。つまり、use命令が不要。