Passed
Pull Request — master (#12)
by Pol
12:14
created

Curry   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 55
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 17
c 1
b 0
f 0
dl 0
loc 55
ccs 10
cts 10
cp 1
rs 10
wmc 6

4 Methods

Rating   Name   Duplication   Size   Complexity  
A of() 0 18 2
A curryN() 0 6 1
A getArguments() 0 3 1
A isComplete() 0 3 2
1
<?php
2
3
/**
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 */
7
8
declare(strict_types=1);
9
10
namespace loophp\fpt;
11
12
use Closure;
13
use Generator;
14
use ReflectionFunction;
15
16
use function count;
17
18
/**
19
 * Stateless "Curry" application.
20
 *
21
 * @psalm-immutable
22
 *
23
 * phpcs:disable Generic.Files.LineLength.TooLong
24
 */
25
final class Curry
26
{
27
    /**
28
     * @psalm-pure
29 4
     */
30
    public static function of(): Closure
31
    {
32
        return
33
            /**
34
             * @param Closure|callable-string $callable
0 ignored issues
show
Documentation Bug introduced by
The doc comment Closure|callable-string at position 2 could not be parsed: Unknown type name 'callable-string' at position 2 in Closure|callable-string.
Loading history...
35 4
             */
36
            static function (callable $callable, int $arity = 0, mixed ...$arguments): mixed {
37
                if (0 === $arity) {
38
                    $reflection = (new ReflectionFunction($callable));
39
                    $parameters = $reflection->getNumberOfParameters();
40
                    $requiredParameters = $reflection->getNumberOfRequiredParameters();
41 4
                }
42 4
43
                return self::curryN(
44 4
                    $callable,
45 4
                    $parameters ?? $arity,
46
                    $requiredParameters ?? $arity,
47
                    ...$arguments
48
                );
49
            };
50
    }
51
52
    /**
53
     * @param Closure|callable-string $callable
0 ignored issues
show
Documentation Bug introduced by
The doc comment Closure|callable-string at position 2 could not be parsed: Unknown type name 'callable-string' at position 2 in Closure|callable-string.
Loading history...
54
     */
55
    private static function curryN(callable $callable, int $parameters, int $requiredParameters, mixed ...$arguments): mixed
56
    {
57
        return match (true) {
58
            0 === $requiredParameters => static fn (): mixed => ($callable)(),
59
            self::isComplete(count($arguments), $parameters, $requiredParameters) => ($callable)(...$arguments),
60
            default => static fn (mixed ...$args): mixed => self::curryN($callable, $parameters, $requiredParameters, ...self::getArguments($arguments, $args))
61 4
        };
62
    }
63 4
64 4
    /**
65
     * @psalm-pure
66
     *
67
     * @psalm-param list<mixed> $args
68
     * @psalm-param list<mixed> $argsNext
69
     *
70
     * @psalm-return Generator<int, mixed>
71 4
     */
72
    private static function getArguments(array $args, array $argsNext): Generator
73
    {
74
        return yield from array_merge($args, $argsNext);
75
    }
76
77
    private static function isComplete(int $arguments, int $parameters, int $requiredParameters): bool
78
    {
79
        return $arguments === $parameters || $arguments === $requiredParameters;
80
    }
81
}
82