From 66705f3e31512756d3ba633ddf75366e283a5e94 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Tue, 27 Oct 2026 22:11:15 +0100 Subject: [PATCH] share apply dispatch with compiled fixed functions --- src/Utils/FixedFunction.php | 19 ++------------- src/Utils/index.php | 48 ++++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/Utils/FixedFunction.php b/src/Utils/FixedFunction.php index dc2d92b..8eddfed 100644 --- a/src/Utils/FixedFunction.php +++ b/src/Utils/FixedFunction.php @@ -11,10 +11,10 @@ namespace Kadet\Functional\Utils; use function Kadet\Functional\apply; +use function Kadet\Functional\applyWithArity; use Kadet\Functional\Compilable; use function Kadet\Functional\compile; use Kadet\Functional\Decorator; -use function Kadet\Functional\partial; use function Kadet\Functional\reflect; class FixedFunction implements Decorator, Compilable @@ -70,22 +70,7 @@ class FixedFunction implements Decorator, Compilable $call = $fixed instanceof CurriedFunction ? $fixed : compile($fixed); $self = static function (...$args) use (&$self, $fixed, $call, $variadic, $required, $all) { - array_unshift($args, $self); - - switch (true) { - case $variadic: - return partial($fixed, ...$args); - - case count($args) >= $all: - $applied = $call(...array_slice($args, 0, $all)); - return is_callable($applied) ? apply($applied, ...array_slice($args, $all)) : $applied; - - case count($args) >= $required: - return $call(...$args); - - default: - return partial($fixed, ...$args); - } + return applyWithArity($fixed, $call, $variadic, $required, $all, [$self, ...$args]); }; return $self; diff --git a/src/Utils/index.php b/src/Utils/index.php index af87561..5ade686 100644 --- a/src/Utils/index.php +++ b/src/Utils/index.php @@ -24,29 +24,45 @@ function apply(callable $callable, ...$args) { try { $reflection = reflect($callable); - $required = $reflection->getNumberOfRequiredParameters(); - $all = $reflection->getNumberOfParameters(); - switch (true) { - case $reflection->isVariadic(): - return partial($callable, ...$args); - - case count($args) >= $all: - $applied = $callable(...array_slice($args, 0, $all)); - return is_callable($applied) ? apply($applied, ...array_slice($args, $all)) : $applied; - - case count($args) >= $required: - return $callable(...$args); - - default: - return partial($callable, ...$args); - } + 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); } } +/** + * The argument dispatch of apply(), with the arity of $callable already known: it calls $call when there are enough + * arguments and partially applies $callable otherwise. + * + * @internal + */ +function applyWithArity(callable $callable, callable $call, bool $variadic, int $required, int $all, array $args) +{ + switch (true) { + case $variadic: + return partial($callable, ...$args); + + case count($args) >= $all: + $applied = $call(...array_slice($args, 0, $all)); + return is_callable($applied) ? apply($applied, ...array_slice($args, $all)) : $applied; + + case count($args) >= $required: + return $call(...$args); + + default: + return partial($callable, ...$args); + } +} + function curry(callable $callable, ?int $threshold = null, ...$args): CurriedFunction { return new CurriedFunction($callable, $threshold, ...$args);