/** * orL, short for logical or, a stand in for || * @sig ($lhs)->($rhs)-> boolean $z * @param mixed $lhs * @param mixed $rhs * @return boolean|\Closure */ function orL($lhs = null, $rhs = null) { // Unwrapped curry to have a smaller stack. $_ = __PRIVATE__::placeholder(); $arity = func_num_args(); $lhsX = $arity > 0 && $lhs !== $_; $rhsX = $arity > 1 && $rhs !== $_; if ($lhsX && $rhsX) { // Both defined // Return the result return $lhs || $rhs; } if ($lhsX) { if ($lhs) { $alwaysTrue = function ($rhs = null) use(&$alwaysTrue, $_) { return func_num_args() !== 0 && $rhs !== $_ ? true : $alwaysTrue; }; return $alwaysTrue; } $rightDeterminate = function ($rhs = null) use(&$rightDeterminate, $_) { return func_num_args() !== 0 && $rhs !== $_ ? (bool) $rhs : $rightDeterminate; }; return $rightDeterminate; } if ($rhsX) { // Is the right hand side defined? $indeterminate = function ($lhs = null) use($_, &$indeterminate, $rhs) { return func_num_args() !== 0 && $lhs !== $_ ? $lhs || $rhs : $indeterminate; }; return $indeterminate; } // both are undefined, send a wrapped version of itself. (rare) return __PRIVATE__::$instance[orL]; }
/** * Takes a callable, then flips the two next arguments before calling the function * @param callable * @return \Closure f(a, b, ....z) -> f(b,a, ... z) */ function flip(callable $hof) { // Use the variadic internal static form of curry. We don't want to eat the rest of the args. return __PRIVATE__::curryGiven([], 2, function (...$args) use($hof) { $temp = $args[0]; $args[0] = $args[1]; $args[1] = $temp; return call_user_func_array($hof, $args); }); }
/** * andL, short for logical and, a stand in for && * @sig ($lhs)->($rhs)-> boolean $z * @param mixed $lhs * @param mixed $rhs * @return boolean|\Closure */ function andL($lhs = null, $rhs = null) { // Unwrapped curry to have a smaller stack. $_ = __PRIVATE__::placeholder(); $arity = func_num_args(); $lhsX = $arity > 0 && $lhs !== $_; $rhsX = $arity > 1 && $rhs !== $_; if ($lhsX && $rhsX) { // Both defined // Return the result return $lhs && $rhs; } if ($lhsX) { // first is defined if (!$lhs) { // if lhs is false, then the result is always false $alwaysFalse = function ($rhs = null) use(&$alwaysFalse, $_) { return func_num_args() !== 0 && $rhs !== $_ ? false : $alwaysFalse; }; return $alwaysFalse; } // Otherwise the value is determined only by the rhs $rightDeterminate = function ($rhs = null) use($_, &$rightDeterminate) { return func_num_args() !== 0 && $rhs !== $_ ? (bool) $rhs : $rightDeterminate; }; return $rightDeterminate; } if ($rhsX) { // Is the right hand side defined? $indeterminate = function ($lhs = null) use($_, &$indeterminate, $rhs) { return func_num_args() !== 0 && $lhs !== $_ ? $lhs && $rhs : $indeterminate; }; return $indeterminate; } // both are undefined, send a wrapped version of itself. (rare) return __PRIVATE__::$instance[andL]; }
<?php namespace PHPixme; /** * ufo, short for the space ship operator, or the three way comparison, a stand in for <=> * @sig ($lhs)->($rhs)-> boolean $z * @param mixed $lhs * @param mixed $rhs * @return int|\Closure */ function ufo($lhs = null, $rhs = null) { return call_user_func_array(__PRIVATE__::$instance[ufo], func_get_args()); } const ufo = __NAMESPACE__ . '\\ufo'; __PRIVATE__::$instance[ufo] = __PRIVATE__::curryExactly2(function ($lhs, $rhs) { return $lhs != $rhs ? $lhs > $rhs ? 1 : -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; });
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; }; });
<?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; });
<?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)); });
<?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()); }; });
<?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; }; });
<?php /** * Created by PhpStorm. * User: rgladson * Date: 5/12/2016 * Time: 12:03 PM */ namespace PHPixme; /** * Wrap a function in an argument that will eat all but n arguments * @param int $arity * @param callable = $hof * @return \Closure * @sig Integer -> Callable (* -> x) -> \Closure (* -> x) */ function nAry($arity = null, callable $hof = null) { return call_user_func_array(__PRIVATE__::$instance[nAry], func_get_args()); } const nAry = __NAMESPACE__ . '\\nAry'; __PRIVATE__::$instance[nAry] = __PRIVATE__::curryExactly2(function ($number = 0, $hof = null) { __CONTRACT__::argIsAPositiveOrZeroInt($number); __CONTRACT__::argIsACallable($hof, 1); return function () use($number, $hof) { $args = func_get_args(); return call_user_func_array($hof, array_slice($args, 0, $number)); }; });
<?php namespace PHPixme; /** * pluckArrayWith * Creates a function to access the property of an object * @param string $accessor * @param array $container * @return \Closure ($object) -> object->accessor * @sig String -> Array -> \Closure (->x) */ function pluckArrayWith($accessor = null, $container = null) { return call_user_func_array(__PRIVATE__::$instance[pluckArrayWith], func_get_args()); } const pluckArrayWith = __NAMESPACE__ . '\\pluckArrayWith'; __PRIVATE__::$instance[pluckArrayWith] = __PRIVATE__::curryExactly2(function ($accessor, $container) { return $container[$accessor]; });
<?php namespace PHPixme; /** * xorL, short for logical xor, a stand in for xor keyword * @sig ($lhs)->($rhs)-> boolean $z * @param mixed $lhs * @param mixed $rhs * @return boolean|\Closure */ function xorL($lhs = null, $rhs = null) { return call_user_func_array(__PRIVATE__::$instance[xorL], func_get_args()); } const xorL = __NAMESPACE__ . '\\xorL'; __PRIVATE__::$instance[xorL] = __PRIVATE__::curryExactly2(function ($lhs, $rhs) { return $lhs xor $rhs; });
namespace PHPixme; /** * @param callable $hof * @param mixed = $startVal * @param \Traversable= $traversable * @return \Closure|mixed * @sig (Callable (a, b) -> a) -> a -> \Traversable [b] -> a */ function foldRight($hof = null, $startVal = null, $traversable = null) { return call_user_func_array(__PRIVATE__::$instance[foldRight], func_get_args()); } const foldRight = __NAMESPACE__ . '\\foldRight'; __PRIVATE__::$instance[foldRight] = __PRIVATE__::curryExactly3(function ($hof, $startVal, $arrayLike) { __CONTRACT__::argIsACallable($hof); __CONTRACT__::argIsATraversable($arrayLike, 2); if ($arrayLike instanceof FoldableInterface) { return $arrayLike->foldRight($hof, $startVal); } // Use traversableToArray, because right is non-lazy on \Traversable $array = __PRIVATE__::traversableToArray($arrayLike); $output = $startVal; end($array); while (!is_null($key = key($array))) { $output = call_user_func($hof, $output, current($array), $key, $arrayLike); prev($array); } return $output; });
<?php namespace PHPixme; /** * pluckObjectWith * Creates a function to access the property of an object * @param string $accessor * @param Object $container * @return \Closure ($object) -> object->accessor * @sig String -> Object -> \Closure (->x) */ function pluckObjectWith($accessor = null, $container = null) { return call_user_func_array(__PRIVATE__::$instance[pluckObjectWith], func_get_args()); } const pluckObjectWith = __NAMESPACE__ . '\\pluckObjectWith'; __PRIVATE__::$instance[pluckObjectWith] = __PRIVATE__::curryExactly2(function ($accessor, $container) { return $container->{$accessor}; });
<?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); }; });
<?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; });
<?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); });
<?php namespace PHPixme; /** * After Decorator * Decorate a callable using the return value of the decorated callable as the argument * for this decorative function. It does not modify the return value. * @param Callable $decorator * @param Callable $fn * @return \Closure * @sig Callable (x->) -> Callable (*->x) -> Closure (*->x) */ function after($decorator = null, $fn = null) { return call_user_func_array(__PRIVATE__::$instance[after], func_get_args()); } const after = __NAMESPACE__ . '\\after'; __PRIVATE__::$instance[after] = __PRIVATE__::curryExactly2(function ($decorator, $fn) { __CONTRACT__::argIsACallable($decorator); __CONTRACT__::argIsACallable($fn, 1); return function () use($decorator, $fn) { $value = call_user_func_array($fn, func_get_args()); call_user_func($decorator, $value); return $value; }; });
<?php namespace PHPixme; /** * notB, not binary, invert, or 2's compliment, a stand in for ~ * @sig (int $rhs) -> int $z * @param int $rhs * @return int|\Closure */ function notB($rhs = null) { return call_user_func_array(__PRIVATE__::$instance[notB], func_get_args()); } const notB = __NAMESPACE__ . '\\notB'; __PRIVATE__::$instance[notB] = __PRIVATE__::curryExactly1(function ($rhs) { return ~$rhs; });
<?php namespace PHPixme; /** * Before decorator * Wraps a Closure around a callable, running the decorating callable with the same arguments * before executing and returning the value of the decorated function * @param Callable $decorator * @param Callable $fn * @return \Closure * @sig Callable (*->) -> Callable (*->x) -> Closure (*->x) */ function before($decorator = null, $fn = null) { return call_user_func_array(__PRIVATE__::$instance[before], func_get_args()); } const before = __NAMESPACE__ . '\\before'; __PRIVATE__::$instance[before] = __PRIVATE__::curryExactly2(function ($decorator, $fn) { __CONTRACT__::argIsACallable($decorator); __CONTRACT__::argIsACallable($fn, 1); return function () use($decorator, $fn) { $args = func_get_args(); call_user_func_array($decorator, $args); return call_user_func_array($fn, $args); }; });
<?php namespace PHPixme; /** * gte, short for greater than or equal to, a stand in for >= * @sig ($lhs)->($rhs)-> boolean $z * @param mixed $lhs * @param mixed $rhs * @return boolean|\Closure */ function gte($lhs = null, $rhs = null) { return call_user_func_array(__PRIVATE__::$instance[gte], func_get_args()); } const gte = __NAMESPACE__ . '\\gte'; __PRIVATE__::$instance[gte] = __PRIVATE__::curryExactly2(function ($lhs, $rhs) { return $lhs > $rhs; });
<?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; });
<?php namespace PHPixme; /** * shiftL, or shift left, a stand in for << * @param int|float $lhs * @param int $rhs * @return int|\Closure */ function shiftL($lhs = null, $rhs = null) { return call_user_func_array(__PRIVATE__::$instance[shiftL], func_get_args()); } const shiftL = __NAMESPACE__ . '\\shiftL'; __PRIVATE__::$instance[shiftL] = __PRIVATE__::curryExactly2(function ($lhs, $rhs) { return $lhs << $rhs; });
<?php namespace PHPixme; /** * nid, short for not the identity, or not strictly equals, a stand in for !== * @sig ($lhs)->($rhs)-> boolean $z * @param mixed $lhs * @param mixed $rhs * @return boolean|\Closure */ function nid($lhs = null, $rhs = null) { return call_user_func_array(__PRIVATE__::$instance[nid], func_get_args()); } const nid = __NAMESPACE__ . '\\nid'; __PRIVATE__::$instance[nid] = __PRIVATE__::curryExactly2(function ($lhs, $rhs) { return $lhs !== $rhs; });