Completed
Push — master ( 3e4d42...ec481a )
by Amine
10s
created

_functions.php ➔ _merge_args()   B

Complexity

Conditions 5
Paths 1

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 1
nop 3
dl 0
loc 16
rs 8.8571
c 0
b 0
f 0
1
<?php namespace Tarsana\Functional;
2
/**
3
 * This file contains common internal functions
4
 * @file
5
 */
6
7
/**
8
 * Adds the `Tarsana\Functional` namespace to a function name.
9
 * This is useful to pass non-curried functions as parameter.
10
 * ```php
11
 * F\_f('foo'); //=> 'Tarsana\Functional\foo'
12
 * ```
13
 *
14
 * @signature String -> Sring
15
 * @param  string $name
16
 * @return string
17
 */
18
function _f($name) {
19
    $name = "Tarsana\\Functional\\{$name}";
20
    return $name;
21
}
22
23
/**
24
 * Gets the number of arguments of a function.
25
 * ```php
26
 * F\_number_of_args(function($x, $y){}); //=> 2
27
 * ```
28
 *
29
 * @signature (* -> *) -> Number
30
 * @param  callable $fn
31
 * @return int
32
 */
33
function _number_of_args($fn) {
34
    $reflector = is_array($fn) ?
35
        new \ReflectionMethod($fn[0], $fn[1]) :
36
        new \ReflectionFunction($fn);
37
    return $reflector->getNumberOfRequiredParameters();
38
}
39
40
/**
41
 * Checks if `$a` is an argument placeholder.
42
 * ```php
43
 * F\_is_placeholder(F\__()); //=> true
44
 * F\_is_placeholder('other thing'); //=> false
45
 * ```
46
 *
47
 * @signature * -> Boolean
48
 * @param  mixed  $a
49
 * @return boolean
50
 */
51
function _is_placeholder($a) {
52
    return $a instanceof Placeholder;
53
}
54
55
/**
56
 * Adds new given arguments to the list of bound arguments while filling placeholders.
57
 *
58
 * @signature Number -> [a] -> [a] -> [a]
59
 * @param  int   $fnArgsCount
60
 * @param  array $boundArgs
61
 * @param  array $givenArgs
62
 * @return array
63
 */
64
function _merge_args($fnArgsCount, $boundArgs, $givenArgs) {
65
    $addArgument = function($currentBoundArgs, $arg) use($fnArgsCount) {
66
        $currentBoundArgsCount = count($currentBoundArgs);
67
        $placeholderPosition = 0;
68
        while($placeholderPosition < $currentBoundArgsCount && !_is_placeholder($currentBoundArgs[$placeholderPosition]))
69
            $placeholderPosition ++;
70
        if ($currentBoundArgsCount < $fnArgsCount || $placeholderPosition == $currentBoundArgsCount) {
71
            $currentBoundArgs[] = $arg;
72
        } else { // There is a placeholder and number of bound args >= $fnArgsCount
73
            $currentBoundArgs[$placeholderPosition] = $arg;
74
        }
75
        return $currentBoundArgs;
76
    };
77
78
    return array_reduce($givenArgs, $addArgument, $boundArgs);
79
}
80
81
/**
82
 * Returns the curried version of a function with some arguments bound to it.
83
 *
84
 * @signature (* -> *) -> Number -> [*] -> (* -> *)
85
 * @param  callable $fn
86
 * @param  int $argsCount
87
 * @param  array  $boundArgs
88
 * @return callable
89
 */
90
function _curried_function($fn, $argsCount, $boundArgs = []) {
91
    return function() use($fn, $argsCount, $boundArgs) {
92
        $boundArgs = _merge_args($argsCount, $boundArgs, func_get_args());
0 ignored issues
show
Bug introduced by
Consider using a different name than the imported variable $boundArgs, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.

Change not visible in outer-scope

$x = 1;
$callable = function() use ($x) {
    $x = 2; // Not visible in outer scope. If you would like this, how
            // about using a different variable name than $x?
};

$callable();
var_dump($x); // integer(1)

Change visible in outer-scope

$x = 1;
$callable = function() use (&$x) {
    $x = 2;
};

$callable();
var_dump($x); // integer(2)
Loading history...
93
        $numberOfPlaceholders = count(array_filter($boundArgs, _f('_is_placeholder')));
94
        $numberOfGivenArgs = count($boundArgs) - $numberOfPlaceholders;
95
        if ($numberOfGivenArgs >= $argsCount)
96
            return call_user_func_array($fn, $boundArgs);
97
        return _curried_function($fn, $argsCount, $boundArgs);
98
    };
99
}
100
101
/**
102
 * Non curried version of apply for internal use.
103
 *
104
 * @param  callable $fn
105
 * @param  array    $args
106
 * @return mixed
107
 */
108
function _apply($fn, $args) {
109
    return call_user_func_array($fn, $args);
110
}
111