PHP入門 関数呼び出しと戻り値
複数の戻り値、再帰関数、コールバック関数、名関数、アロー関数について解説しています。
複数の戻り値
関数から複数の戻り値を返したい場合、配列やオブジェクトとして値を1つにまとめた上でreturn命令で戻り値を返します。
例:最大値と最小値を求める
returns.php
<?php
function max_min(float ...$args): array{
//最大値/最小値の順で配列を生成
return [max($args), min($args)];
}
<?php
require_once 'returns.php';
$result = max_min(10, 2, -5, 3, 78);
print_r($result);
[$max, $min] = max_min(10, 2, -5 , 3, 78);//➊
print "最大値:{$max}、最小値:{$min}";
戻り値に含まれる個別の要素をそのまま変数に振り分けたい場合はは、➊のように分割代入を利用します。分割代入は関数から返された配列の内容を、変数に振り分けます。
再帰関数
再帰関数(Recursive Function)とは、ある関数が自分自身を呼び出すこと、また、そのような関数です。再帰関数を利用することで、階乗計算のように同種の手続きを繰り返し呼び出すような処理を短いコードで表現できます。
<?php
function factorial(int $num): int {
if($num !== 0){
return $num * factorial($num -1);
}
return 1;
}
print factorial(5);//結果:120
再帰関数では、再帰の終了点が必要になります。自然数$numが0である場合に、戻り値を1としています。このような終了点がないと、再帰関数は永遠に再帰呼び出しを続けることになってしまいます。
可変関数
可変関数(Variable Functions)とは「$変数名()」の形式で呼び出せる関数のことです。これによって、変数名に応じて対応する関数を検索&実行できます。
<?php
function getTriangleArea(float $base,float $height): float {
return $base * $height /2;
}
$name ='getTriangleArea';
$area = $name(8, 10);
print "三角の面積は{$area}です。";
可変関数を利用することで、変数によって動的に呼び出す関数を振り分けることができるようになります。
高階関数の実装
関数そのものを引数として渡したり、あるいは戻り値として返したりするための関数です。
例
<?php
function myArrayWalk(array $array, callable $func): void{
//配列$arrayの内容を順に処理
foreach ($array as $key => $value){
$func($value, $key);
}
}
function showItem(mixed $value, int | string $key): void {
print "{$key}:{$value}<br />";
}
$data = ['山田','杉山','佐藤','鈴木','田中'];
myArrayWalk($data, 'showItem');
ユーザー定義関数$funcは、引数として配列の値、キー(インデックス番号)を受け取り、それぞれの配列要素に対して、任意の処理を行うものとします。$funcにセットされているのは、showItem関数です。可変関数の機能を利用することで、このように引数を経由して実行する関数を決めることができます。
無名関数(クロージャー)
クロージャ関数は、無名関数(匿名関数)という名前を持たない関数です。その場限りでしか利用しない使い捨ての関数に名前を付けるのは無駄なので、無名関数をを使用します。
構文:無名関数
function(仮引数,・・・){
//任意の処理
return 戻り値;
}
例
<?php
function myArrayWalk(array $array, callable $func): void{
//配列$arrayの内容を順に処理
foreach ($array as $key => $value){
$func($value, $key);
}
}
$data = ['山田','杉山','佐藤','鈴木','田中'];
myArrayWalk($data,
function($value, $key){
print "{$key}:{$value}<br />";
}
);
無名関数によって名前がなくなっただけでなく、高階関数呼び出しのコードに関数定義を直接埋め込めるようになります。
無名関数は、文字列や数値などのリテラルと同じく、変数に代入することもできます。
$triangle = function($base, $height){~};
ただし、この場合は、ブロックの末尾にセミコロン(;)が必要となります。{~}はブロックの終わりだけではなく、いわゆる関数利点の一部であるからです。
無名関数の型宣言
一般的な関数と同じく、無名関数でも型宣言を付与できます。
function(mixed $value, int | string $key): void{
print "{$key}:{$value}<br />";
}
親スコープの変数を引き継ぐ(use命令)
無名関数(クロージャー)では、親スコープから変数を引き継ぐこともできます。
<?php
function myArrayWalk(array $array, callable $func): void{
//配列$arrayの内容を順に処理
foreach ($array as $key => $value){
$func($value, $key);
}
}
//結果を求めるための関数
$data = [100,50,10,5];
//結果値を格納するための変数
$result = 0;
myArrayWalk($data,function($value, $key) use(&$result){
$result += $value;
}
);
print "合計値:{$result}"; //結果:合計値:165
親スコープの変数を引き継ぐのはuse命令の役割です。ここでは$result1つを引き継いでいますが、カンマ区切りで複数の変数を引き継ぐこともできます。
myArrayWalk($data,
function($value, $key) use(&$result){・・・・}
「&」演算子で参照渡ししているのは、無名関数の中で$resultに加算結果を書き戻しているためです。use命令でも、引数のときと同じく、値渡しが既定なので、「&」がないと結果が反映されません。
アロー関数
PHP7.4以降では、無名関数をさらにシンプルに表せる仕組みとして、アロー関数が追加されました。
構文:アロー関数
fn(仮引数, ...) => 任意の式
アロー関数がシンプルである、というのは、「function」が「fn」になったり、引数と関数本体を「=>」で接続するなどの見た目以外にも、任意の式の中で親スコープの変数を暗黙的に使用できる点が大きく異なります。
<?php
$keys = ['十','百','千','万','億'];
$data = ['億','千'];
usort($data,fn($a, $b)=> array_search($a, $keys) <=> array_search($b, $keys));
無名関数の中で$keysを参照するには、use命令を利用しなければなりません。しかし、アロー関数はでは不要です。PHP8.0の時点では、アロー関数では単一の式しか書けないという制限があります。