* * Full license available in separate LICENSE file */ namespace Kadet\Functional; use Kadet\Functional\Utils\CurriedFunction; use Kadet\Functional\Utils\FixedFunction; use Kadet\Functional\Utils\FunctionPipeline; use Kadet\Functional\Utils\MemoizedFunction; use Kadet\Functional\Utils\PartiallyAppliedFunction; use function Kadet\Functional\Internal\applyWithArity; function partial(callable $callable, ...$args): PartiallyAppliedFunction { return new PartiallyAppliedFunction($callable, ...$args); } function apply(callable $callable, ...$args) { try { $reflection = reflect($callable); return applyWithArity( $callable, $callable, $reflection->isVariadic(), $reflection->getNumberOfRequiredParameters(), $reflection->getNumberOfParameters(), $args ); } catch (\ReflectionException $exception) { // if cannot gather necessary information for intelligent application just use normal one return $callable(...$args); } } function curry(callable $callable, ?int $threshold = null, ...$args): CurriedFunction { return new CurriedFunction($callable, $threshold, ...$args); } function uncurry(CurriedFunction $curried): PartiallyAppliedFunction { return $curried->uncurry(); } function pipe(...$functions) { return new FunctionPipeline(...$functions); } function fix(callable $callable, ...$args) { $f = new FixedFunction($callable); return $args ? apply($f, ...$args) : $f; } function memoize(callable $callable) { return new MemoizedFunction($callable); } /** * Flattens a callable into a plain closure. Compilable objects (decorators, pipelines, predicates) are compiled, so * calling the result does not go through them, also when given as a closure of their `__invoke` (e.g. `$pipe(...)`); * any other callable is converted with closure(). */ function compile(callable $callable): \Closure { if ($callable instanceof \Closure) { $reflection = new \ReflectionFunction($callable); $bound = $reflection->getClosureThis(); return $bound instanceof Compilable && $reflection->getName() === '__invoke' ? $bound->compile() : $callable; } return $callable instanceof Compilable ? $callable->compile() : closure($callable); }