Интересная задачка от pikabu

Alex Komp
Alex Komp
Sep 9, 2018 · 3 min read

Пикабу ищет бекэндеров, ровно как и фронтэндеров, и бекэнд у них на PHP. Чтобы не тратиться на HR’ов они сделали специальные страницы с задачами чтобы отсеять самый треш. Несколько заметок по этому поводу, а потом разбор интересной задачки.

  1. Аудитория у Пикабу настолько большая (для отдельного ресурса, понятно с mail.ru и yandex они не сравнятся), что они могут не сильно тратиться на HR’ов для поиска технического специалиста.
  2. Преобладают задачки на знание именно PHP, а не баз данных и прочего побочного вроде очередей или хотя бы тестрования. Понятно, что Пикабу достаточно простой сайт и скорее всего даже без фреймворка(тут это не минус, а плюс), но всё же, данные откуда-то берутся и куда-то кладутся, да тестировать всё это бы неплохо и эти знания надо бы проверить.
  3. Первые 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);
}

Ну и весь код

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade