Примеры использования лямбда-выражений в PHP
Анонимные функции в PHP: основы и варианты использования
Анонимная функция (также называемая лямбдой) представляет собой функцию без имени. Она может быть сохранена в переменную, передана в качестве аргумента другой функции или возвращена из функции. Это мощный инструмент для создания гибкого кода, особенно при работе с массивами и функциями высшего порядка.
Основной способ создания
Анонимную функцию создают с помощью ключевого слова function и присваивают переменной.
$square = function($x) {
return $x * $x;
};
echo $square(5); // 25анонимная функция php (анонимные функции в php)
После закрывающей фигурной скобки обязательно ставится точка с запятой. Вызов происходит как у обычной функции.
Типичные ошибки:
Пропущенная точка с запятой после определения вызывает синтаксическую ошибку PHP.
Попытка вызвать анонимную функцию до её присвоения переменной приведет к ошибке undefined function.
Как применить анонимную функцию ко всем элементам массива?
Функция array_map принимает callback и массив, возвращая новый массив.
$numbers = [1, 2, 3, 4];
$squared = array_map(function($n) {
return $n * $n;
}, $numbers);
print_r($squared); // [1, 4, 9, 16]стрелочные функции php (стрелочные функции в php)
Callback выполняется для каждого элемента, результат собирается в новый массив. Исходный массив не изменяется.
Если внутри callback требуется обратиться к внешней переменной, необходимо использовать use, иначе переменная будет не определена.
Как использовать внешние переменные внутри анонимной функции?
Конструкция use позволяет захватить переменные из родительской области видимости.
$factor = 3;
$multiply = function($x) use ($factor) {
return $x * $factor;
};
echo $multiply(4); // 12
Переменная $factor копируется в замыкание. Чтобы изменить внешнюю переменную, используйте ссылку: use (&$factor).
Если переменная, переданная в use, не существует на момент объявления, PHP выдаст предупреждение. Также следует помнить, что изменения переменной внутри замыкания не влияют на оригинал, если не передана ссылка.
Как создать фабрику функций с помощью замыкания?
Функция может возвращать анонимную функцию, которая сохраняет своё окружение.
function createGreeter($greeting) {
return function($name) use ($greeting) {
return $greeting . ', ' . $name . '!';
};
}
$helloGreeter = createGreeter('Hello');
echo $helloGreeter('World'); // Hello, World!
Каждый вызов createGreeter создаёт новую анонимную функцию с собственным значением $greeting.
Значение захваченной переменной фиксируется в момент создания замыкания. Для изменения захваченной переменной внутри возвращаемой функции нужно передавать её по ссылке.
Как сделать анонимную функцию рекурсивной?
Для рекурсии необходимо передать ссылку на саму функцию через use (&$func).
$factorial = function($n) use (&$factorial) {
if ($n <= 1) return 1;
return $n * $factorial($n - 1);
};
echo $factorial(5); // 120
Без ссылки $factorial внутри функции не определена.
Если забыть амперсанд, будет бесконечный цикл или ошибка, так как $factorial внутри будет null.
Чем отличаются стрелочные функции от обычных анонимных?
Стрелочные функции (fn) имеют лаконичный синтаксис и автоматически захватывают переменные по значению.
$factor = 2;
$multiply = fn($x) => $x * $factor;
echo $multiply(5); // 10
Не требуется use. Тело может содержать только одно выражение, результат которого автоматически возвращается.
Стрелочные функции не подходят для многострочной логики или инструкций вроде return, echo и т.д. Для сложных сценариев используйте обычные анонимные функции.
Расширенные примеры анонимных функций в PHP
Ниже приведены более сложные сценарии использования анонимных функций.
Пример 1: Сумма квадратов нечетных чисел с array_reduce
$numbers = [1, 2, 3, 4, 5, 6];
$sumOddSquares = array_reduce($numbers, function($carry, $item) {
if ($item % 2 != 0) {
$carry += $item * $item;
}
return $carry;
}, 0);
echo $sumOddSquares; // 1+9+25 = 35
35
Пример 2: Динамический фильтр по диапазону
function createRangeFilter($min, $max) {
return function($value) use ($min, $max) {
return $value >= $min && $value <= $max;
};
}
$filter = createRangeFilter(10, 20);
$values = [5, 15, 25, 10, 20, 30];
$filtered = array_filter($values, $filter);
print_r(array_values($filtered)); // [15, 10, 20]
Array ( [0] => 15 [1] => 10 [2] => 20 )
Пример 3: Мемоизация (кэширование) с помощью замыкания
function memoize($func) {
$cache = [];
return function($arg) use ($func, &$cache) {
if (!array_key_exists($arg, $cache)) {
$cache[$arg] = $func($arg);
}
return $cache[$arg];
};
}
$factorial = memoize(function($n) use (&$factorial) {
if ($n <= 1) return 1;
return $n * $factorial($n - 1);
});
echo $factorial(10); // 3628800
echo $factorial(10); // из кэша (результат тот же)
3628800
Пример 4: Композиция функций
$addOne = fn($x) => $x + 1;
$multiplyTwo = fn($x) => $x * 2;
$compose = function($f, $g) {
return function($x) use ($f, $g) {
return $g($f($x));
};
};
$addOneThenMultiplyTwo = $compose($addOne, $multiplyTwo);
echo $addOneThenMultiplyTwo(5); // (5+1)*2 = 12
12
Пример 5: Инициализация статического свойства класса
class Config {
public static $data = [];
}
Config::$data = (function() {
return ['db' => 'mysql', 'host' => 'localhost'];
})();
print_r(Config::$data);
Array ( [db] => mysql [host] => localhost )
Пример 6: Изменение внешней переменной по ссылке
$counter = 0;
$increment = function() use (&$counter) {
$counter++;
};
$increment();
$increment();
echo $counter; // 2
2
Пример 7: Сортировка с несколькими условиями через usort
$data = [
['name' => 'Alice', 'age' => 30],
['name' => 'Bob', 'age' => 25],
['name' => 'Charlie', 'age' => 30],
];
usort($data, function($a, $b) {
if ($a['age'] != $b['age']) {
return $a['age'] - $b['age'];
}
return strcmp($a['name'], $b['name']);
});
print_r($data);
Array ( [0] => Array ( [name] => Bob [age] => 25 ) [1] => Array ( [name] => Alice [age] => 30 ) [2] => Array ( [name] => Charlie [age] => 30 ) )