Example #1
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);
});
Example #2
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;
});
Example #3
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));
});
Example #4
0
 /**
  * @inheritdoc
  * @return Exclusive
  */
 public function flatten()
 {
     return __CONTRACT__::contentIsA(Exclusive::class, $this->value);
 }
Example #5
0
 /**
  * @inheritdoc
  */
 public function apply(FunctorInterface $functor)
 {
     return $functor->map(__CONTRACT__::contentIsACallable($this->value));
 }
Example #6
0
<?php

namespace PHPixme;

/**
 * @param Callable $decorator
 * @param Callable $fn
 * @return \Closure
 */
function except($decorator = null, $fn = null)
{
    return call_user_func_array(__PRIVATE__::$instance[except], func_get_args());
}
const except = __NAMESPACE__ . '\\except';
__PRIVATE__::$instance[except] = __PRIVATE__::curryExactly2(function ($predicate, $fn) {
    __CONTRACT__::argIsACallable($predicate);
    __CONTRACT__::argIsACallable($fn, 1);
    return function () use($predicate, $fn) {
        $args = func_get_args();
        return call_user_func_array($predicate, $args) ? null : call_user_func_array($fn, $args);
    };
});
Example #7
0
 /**
  * @return self
  * @throws \UnexpectedValueException if the data-set could not be flattened
  */
 public function flatten()
 {
     return __CONTRACT__::contentIsA(self::class, $this->contents);
 }
Example #8
0
 /**
  * Ensures the return for the callback is exactly the same type as the object
  * @param mixed $unknown
  * @return self
  * @throws exception\InvalidReturnException
  */
 public static function assertType($unknown)
 {
     return __CONTRACT__::returnIsA(static::class, $unknown);
 }
Example #9
0
<?php

namespace PHPixme;

/**
 * callWith
 * Produce a function that calls a function within a array or object
 * @param string $accessor
 * @param object|array $container
 * @return \Closure ($container) -> ((args) -> $container{[$accessor]}(...args))
 * @sig String -> Object|Array -> \Closure (*->x)
 */
function callWith($accessor = null, $container = null)
{
    return call_user_func_array(__PRIVATE__::$instance[callWith], func_get_args());
}
const callWith = __NAMESPACE__ . '\\callWith';
__PRIVATE__::$instance[callWith] = __PRIVATE__::curryExactly2(function ($accessor, $container) {
    $callable = __CONTRACT__::composedIsACallable(is_array($container) ? array_key_exists($accessor, $container) ? $container[$accessor] : null : [$container, $accessor]);
    return function () use($callable) {
        return call_user_func_array($callable, func_get_args());
    };
});
Example #10
0
<?php

namespace PHPixme;

/**
 * @param callable $hof
 * @param array|\Traversable|FunctorInterface $traversable
 * @return \Closure|mixed
 * @sig Callable (a -> b) -> \Traversable[a] -> \Traversable[b]
 *
 */
function map($hof = null, $traversable = null)
{
    return call_user_func_array(__PRIVATE__::$instance[map], func_get_args());
}
const map = __NAMESPACE__ . '\\map';
__PRIVATE__::$instance[map] = __PRIVATE__::curryExactly2(function ($hof, $traversable) {
    __CONTRACT__::argIsACallable($hof);
    __CONTRACT__::argIsATraversable($traversable, 1);
    if ($traversable instanceof FunctorInterface) {
        return $traversable->map($hof);
    }
    $output = [];
    foreach (__PRIVATE__::protectTraversable($traversable) as $key => $value) {
        $output[$key] = call_user_func($hof, $value, $key, $traversable);
    }
    return $output;
});
Example #11
0
<?php

namespace PHPixme;

/**
 * @param callable $hof
 * @param mixed $startVal
 * @param \Traversable $traversable
 * @return \Closure|mixed
 * @sig (Callable (a, b) -> a) -> a -> \Traversable [b] -> a
 */
function fold($hof = null, $startVal = null, $traversable = null)
{
    return call_user_func_array(__PRIVATE__::$instance[fold], func_get_args());
}
const fold = __NAMESPACE__ . '\\fold';
__PRIVATE__::$instance[fold] = __PRIVATE__::curryExactly3(function ($hof, $startVal, $arrayLike) {
    __CONTRACT__::argIsACallable($hof);
    if ($arrayLike instanceof FoldableInterface) {
        return $arrayLike->fold($hof, $startVal);
    }
    $output = $startVal;
    foreach (__PRIVATE__::protectTraversable($arrayLike) as $key => $value) {
        $output = call_user_func($hof, $output, $value, $key, $arrayLike);
    }
    return $output;
});
Example #12
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;
    };
});
Example #13
0
 /**
  * @param mixed $unknown
  * @return mixed some child of the parent class
  * @throws exception\InvalidReturnException
  */
 public static final function assertRootType($unknown)
 {
     return __CONTRACT__::returnIsA(self::class, $unknown);
 }
Example #14
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;
    };
});
Example #15
0
<?php

namespace PHPixme;

/**
 * map
 * @param callable $hof
 * @param array|FunctorInterface|\Traversable $collection
 * @return \Closure|$collection
 */
function walk($hof = null, $collection = null)
{
    return call_user_func_array(__PRIVATE__::$instance[walk], func_get_args());
}
const walk = __NAMESPACE__ . '\\walk';
__PRIVATE__::$instance[walk] = __PRIVATE__::curryExactly2(function ($hof, $collection) {
    __CONTRACT__::argIsACallable($hof);
    __CONTRACT__::argIsATraversable($collection, 1);
    if ($collection instanceof FunctorInterface) {
        return $collection->walk($hof);
    }
    $array = __PRIVATE__::getArrayFrom($collection);
    if ($array !== null) {
        array_walk($array, $hof, $collection);
    } else {
        foreach (__PRIVATE__::copyTransversable($collection) as $k => $v) {
            call_user_func($hof, $v, $k, $collection);
        }
    }
    return $collection;
});
Example #16
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;
});
Example #17
0
 /**
  * @inheritdoc
  * @return Either
  */
 public function flattenLeft()
 {
     return __CONTRACT__::contentIsA(static::rootType(), $this->value);
 }