Пример #1
0
namespace PHPixme;

/**
 * @param callable $hof
 * @param \Traversable= $traversable
 * @return \Closure|mixed
 * @sig Callable (a, b -> a) -> \Traversable[a,b] -> a
 */
function reduceRight($hof = null, $traversable = null)
{
    return call_user_func_array(__PRIVATE__::$instance[reduceRight], func_get_args());
}
const reduceRight = __NAMESPACE__ . '\\reduceRight';
__PRIVATE__::$instance[reduceRight] = __PRIVATE__::curryExactly2(function ($hof, $arrayLike) {
    __CONTRACT__::argIsACallable($hof);
    __CONTRACT__::argIsATraversable($arrayLike, 1);
    if ($arrayLike instanceof ReducibleInterface) {
        return $arrayLike->reduceRight($hof);
    }
    // Equalize the usefulness
    $array = __CONTRACT__::isNonEmpty(__PRIVATE__::traversableToArray($arrayLike));
    $output = end($array);
    $value = prev($array);
    // Traverse using the internal pointer to avoid creating additional work
    while (($key = key($array)) !== null) {
        $output = call_user_func($hof, $output, $value, $key, $arrayLike);
        $value = prev($array);
    }
    return $output;
});
Пример #2
0
namespace PHPixme;

/**
 * Takes two functions and has the first consume the output of the second, combining them to a single function
 * @param callable $hofSecond
 * @param callable = $hofFirst
 * @return \Closure
 * @sig (Unary Callable(y -> z), ..., Unary Callable(a -> b), Callable (*->a)) -> \Closure (* -> a)
 */
function combine(callable $hofSecond = null, callable $hofFirst = null)
{
    return call_user_func_array(__PRIVATE__::$instance[combine], func_get_args());
}
const combine = __NAMESPACE__ . '\\combine';
__PRIVATE__::$instance[combine] = __PRIVATE__::curryGiven([], 2, function () {
    $combine = func_get_args();
    foreach ($combine as $idx => $hof) {
        __CONTRACT__::argIsACallable($hof, $idx);
    }
    $combineHead = end($combine);
    $combineTail = array_slice($combine, 0, -1);
    $combineTailSize = count($combineTail);
    return function () use($combineHead, $combineTail, $combineTailSize) {
        $acc = call_user_func_array($combineHead, func_get_args());
        for ($index = $combineTailSize - 1; -1 < $index; $index -= 1) {
            $acc = call_user_func($combineTail[$index], $acc);
        }
        return $acc;
    };
});
Пример #3
0
<?php

namespace PHPixme;

/**
 * Group a traversable by a return value, separating them out into [groupName=>[value...]]
 * @param callable $fn
 * @param array|\Traversable $arrayLike
 * @return array|\Closure
 */
function group($fn = null, $arrayLike = null)
{
    return call_user_func_array(__PRIVATE__::$instance[group], func_get_args());
}
const group = __NAMESPACE__ . '\\group';
__PRIVATE__::$instance[group] = __PRIVATE__::curryExactly2(function ($fn, $arrayLike) {
    __CONTRACT__::argIsACallable($fn);
    __CONTRACT__::argIsATraversable($arrayLike, 1);
    if ($arrayLike instanceof GroupableInterface) {
        return $arrayLike->group($fn);
    }
    $output = [];
    foreach (__PRIVATE__::protectTraversable($arrayLike) as $key => $value) {
        $output[call_user_func($fn, $value, $key, $arrayLike)][] = $value;
    }
    return $output;
});
Пример #4
0
<?php

namespace PHPixme;

/**
 * Take a callable and produce a curried \Closure
 * @param int $arity
 * @param callable = $hof
 * @return \Closure
 * @sig Integer -> Callable (*-> x) -> \Closure (* -> x)
 */
function curry($arity = null, callable $hof = null)
{
    return call_user_func_array(__PRIVATE__::$instance[curry], func_get_args());
}
const curry = __NAMESPACE__ . '\\curry';
__PRIVATE__::$instance[curry] = __PRIVATE__::curryExactly2(function ($arity, $callable) {
    __CONTRACT__::argIsAPositiveOrZeroInt($arity);
    __CONTRACT__::argIsACallable($callable, 1);
    // The function is static so that is easier to recurse,
    // as it shares no state with itself outside its arguments.
    return __PRIVATE__::curryGiven([], $arity, $callable);
});
Пример #5
0
<?php

namespace PHPixme;

// -- Starling --
/**
 * Starling
 * This combinator takes two functions and applies the third across both.
 * The first operand must return a function, which will relieve the result of the second.
 * Useful for combining mappings of the same data together
 * @param callable $x
 * @param callable $y
 * @param mixed $z
 * @return \Closure|mixed
 * @sig Callable x -> Callable y -> z -> a
 */
function S($x = null, $y = null, $z = null)
{
    return call_user_func_array(__PRIVATE__::$instance[S], func_get_args());
}
const S = __NAMESPACE__ . '\\S';
__PRIVATE__::$instance[S] = __PRIVATE__::curryExactly3(function ($x, $y, $z) {
    __CONTRACT__::argIsACallable($x);
    __CONTRACT__::argIsACallable($y, 1);
    return call_user_func(__CONTRACT__::composedIsACallable(call_user_func($x, $z)), call_user_func($y, $z));
});
Пример #6
0
<?php

namespace PHPixme;

/**
 * @param $hofFirst
 * @param callable $hofSecond
 * @return mixed
 * @sig (Callable (* -> a) -> Unary Callable ( a -> b ), ..., Unary Callable (y -> z)) -> \Closure (*->z)
 */
function pipe(callable $hofFirst = null, callable $hofSecond = null)
{
    return call_user_func_array(__PRIVATE__::$instance[pipe], func_get_args());
}
const pipe = __NAMESPACE__ . '\\pipe';
__PRIVATE__::$instance[pipe] = __PRIVATE__::curryGiven([], 2, function ($x) {
    $pipe = func_get_args();
    foreach ($pipe as $index => $value) {
        __CONTRACT__::argIsACallable($value, $index);
    }
    $pipeTail = array_splice($pipe, 1);
    return function () use($x, $pipeTail) {
        $acc = call_user_func_array($x, func_get_args());
        $_pipeTail = $pipeTail;
        foreach ($_pipeTail as $hof) {
            $acc = call_user_func($hof, $acc);
        }
        return $acc;
    };
});