Интересная задачка от pikabu
Пикабу ищет бекэндеров, ровно как и фронтэндеров, и бекэнд у них на PHP. Чтобы не тратиться на HR’ов они сделали специальные страницы с задачами чтобы отсеять самый треш. Несколько заметок по этому поводу, а потом разбор интересной задачки.
- Аудитория у Пикабу настолько большая (для отдельного ресурса, понятно с mail.ru и yandex они не сравнятся), что они могут не сильно тратиться на HR’ов для поиска технического специалиста.
- Преобладают задачки на знание именно PHP, а не баз данных и прочего побочного вроде очередей или хотя бы тестрования. Понятно, что Пикабу достаточно простой сайт и скорее всего даже без фреймворка(тут это не минус, а плюс), но всё же, данные откуда-то берутся и куда-то кладутся, да тестировать всё это бы неплохо и эти знания надо бы проверить.
- Первые 13 вопросов не про программирование, а для создания психологического портрета и напоминают они собеседование на завод (я работал на двух заводах в студенчестве).
Я бы не обратил на это объявление внимание, если бы не задачи, а они очень хороши. Одну я разберу ниже, следующие выложу, как будет время.

Если вы не пишете на PHP, дальше можете не смотреть. Описание задачи ниже, мой ответ в самом низу.
Начинаем разбор. Первое что бросается в глаза, это некоторое подобие частичного применения, возможность передать функцию меньшей арности. Понятно, что это совсем не тру, но и PHP не про это.
И так, это означает, что на выходе мы получаем или некий результат, или функцию, чтобы использовать её дальше. Финалом для нас должна быть некая функция, в которую мы засунем собранные до этого параметры. Так же очевидно, что мы должны передавать все собранные данные до финальной функции, что подразумевает передачу массива(вектора, для чётких неPHPшников) параметров, а последним параметром будет наша функция.
function calc(...$param_arr)
{
//...
if (!is_callable($last_one))
//...
}В случае, если параметр не фукнция, вызовем новую функцию, засунув в неё старую функцию, но с новыми параметрами.

return function (…$new_param) use ($param_arr) {
return call_user_func_array('calc', array_merge($param_arr, $new_param));
};Если последний параметр это функция, то поздравляю у вас есть д̶в̶а̶ ̶с̶т̶у̶л̶а̶ две пути, первый путь, когда функция ожидает на вход именно то количество параметров, что у вас есть и второй путь, когда надо редуцировать. Определить сколько параметров на вход принимает та или иная функция нам поможет старый добрый Reflection.

$func = array_pop($param_arr);
if (count((new ReflectionFunction($func))->getParameters()) === count($param_arr)) {
return call_user_func_array($func, $param_arr);
} else {
return array_reduce($param_arr, $func);
}Ну и весь код
