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

Curry   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 60
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

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

4 Methods

Rating   Name   Duplication   Size   Complexity  
A curryN() 0 9 3
A of() 0 18 2
A getArguments() 0 3 1
A isComplete() 0 5 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
use function func_get_args;
18
19
/**
20
 * Stateless "Curry" application.
21
 *
22
 * @psalm-immutable
23
 *
24
 * phpcs:disable Generic.Files.LineLength.TooLong
25
 */
26
final class Curry
27
{
28
    /**
29 4
     * @psalm-pure
30
     */
31
    public static function of(): Closure
32
    {
33
        return
34
            /**
35 4
             * @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...
36
             */
37
            static function (callable $callable, int $arity = 0, ?int $parameters = null, ?int $requiredParameters = null, mixed ...$arguments): mixed {
38
                if (0 === $arity) {
39
                    $reflection = (new ReflectionFunction($callable));
40
                    $parameters ??= $reflection->getNumberOfParameters();
41 4
                    $requiredParameters ??= $reflection->getNumberOfRequiredParameters();
42 4
                }
43
44 4
                return self::curryN(
45 4
                    $callable,
46
                    $parameters ?? $arity,
47
                    $requiredParameters ?? $arity,
48
                    ...$arguments
49
                );
50
            };
51
    }
52
53
    /**
54
     * @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...
55
     */
56
    private static function curryN(callable $callable, int $parameters, int $requiredParameters, mixed ...$arguments): mixed
57
    {
58
        // Normally the curry function takes one parameter at a time (returns a unary function).
59
        return (0 === $requiredParameters) ?
60
            static fn () => ($callable)() :
61 4
            (
62
                self::isComplete(count($arguments), $parameters, $requiredParameters) ?
63 4
                    ($callable)(...$arguments) :
64 4
                    static fn (mixed ...$args): mixed => self::curryN($callable, $parameters, $requiredParameters, ...self::getArguments($arguments, $args))
65
            );
66
    }
67
68
    /**
69
     * @psalm-pure
70
     *
71 4
     * @psalm-param list<mixed> $args
72
     * @psalm-param list<mixed> $argsNext
73
     *
74
     * @psalm-return Generator<int, mixed>
75
     */
76
    private static function getArguments(array $args, array $argsNext): Generator
77
    {
78
        return yield from array_merge($args, $argsNext);
79
    }
80
81
    private static function isComplete(int $arguments, int $parameters, int $requiredParameters): bool
82
    {
83
        var_dump(func_get_args());
0 ignored issues
show
Security Debugging Code introduced by
var_dump(func_get_args()) looks like debug code. Are you sure you do not want to remove it?
Loading history...
84
85
        return $arguments === $parameters || $arguments === $requiredParameters;
86
    }
87
}
88