Как реализовать каррирование в PHP

612
08 августа 2017, 17:11

Пусть у меня есть анонимная функция

$add = function($a, $b) {
    return $a + $b;
};

Как можно реализовать функцию curry, такую, что:

$add5 = curry($add, [5]);
echo $add5(3); // Выведет 8
echo $add5(5); // Выведет 10
Answer 1

Для этих целей можно использовать функции call_user_func_array, func_get_args и немного магии замыканий.

Например так:

function curry(callable $func, array $args) {
    // Создаем новую анонимную функцию, связывая исходную функцию и
    // массив "зафиксированных" аргументов через замыкание.
    return function () use ($func, $args) {
        // Вызываем исходную функцию и возвращаем ее результат.
        return call_user_func_array(
            $func,
            // Объединяем "зафиксированные" аргументы с теми, что
            // будут переданы в каррированную функцию.
            array_merge($args, func_get_args())
        );
    };
};
$add = function($a, $b) {
    return $a + $b;
};
$add5 = curry($add, [5]);
echo $add5(3); // 8
echo $add5(5); // 10
Answer 2

Оригинал: Еще раз о каррировании и частичном применении в PHP

Код:

<?php
function curry($callback, $args = array()){
/* $callback - исходная функция
   $args     - массив ее аргументов, если они уже определены */
    /* строим каррированную функцию */
    $ret = function() use($callback, $args){
        /* определяем число аргументов исходной функции */
        $func = new ReflectionFunction($callback);
        $num = $func->getNumberOfParameters();
        /* добавляем новые аргументы к уже имеющемуся набору */ 
        $args = array_merge($args, func_get_args());
        /* если уже набралось необходимое число аргументов, */
        if(count($args) >= $num){
            /* то подставляем их в исходную функцию 
               и возвращаем результат вычисления */
            return call_user_func_array($callback, $args);
        }
        /* если же аргументов меньше, чем необходимо, */
        else {
            /* то рекурсивно вызываем каррирование исходной функции
               с более полным набором аргументов */
            return curry($callback, $args);
        }
    };
    return $ret;
}
function add($a, $b) { return $a + $b; }
$add = curry("add");
$inc = $add(1);
$dec = $add(-1);
var_dump($inc(6)); // выведет 7
var_dump($dec(8)); // выведет 7
// PHP7
var_dump($add(1)(2)); // выдает 3

Тест: http://sandbox.onlinephpfunctions.com/code/ec8117e986022b355a19ff0f259623b0d2859df1

READ ALSO
Foreach реализация функций php

Foreach реализация функций php

Доброго времени суток, если имеется массив

449
Почему не используется файл bootstrap.php.cache в Symfony3 под PHP7?

Почему не используется файл bootstrap.php.cache в Symfony3 под PHP7?

Я заметил, что в файле web/appphp дистрибутива Symfony Standard Edition есть следующая конструкция:

382
Выборка из mysql по дате

Выборка из mysql по дате

Есть 2 переменных которых получаем из формы называются они $start_date и $end_dateЕсть запрос к базе

385
ошибка в изменении значения в mysql

ошибка в изменении значения в mysql

Делаю сайт для поиска посылокВсе готово, но надо сделать страницу админки, где можно будет изменять статус посылки

290