いろいろな関数呼び出し

再帰関数

自分自身を呼び出す関数。

<?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にセット
?>
  1. 高階関数higherOrder($array, $func)に任意の配列とコールバック関数名を渡して呼び出す
  2. 関数名が仮変数$funcにセットされる
  3. 配列の要素ごとに、任意の機能を持つ可変関数$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命令が不要。