1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Boudewijn Schoon <[email protected]> |
4
|
|
|
* @copyright Zicht Online <http://zicht.nl> |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
namespace Zicht\Itertools\reductions; |
8
|
|
|
|
9
|
|
|
use Zicht\Itertools\lib\ChainIterator; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Returns a closure that adds two numbers together |
13
|
|
|
* |
14
|
|
|
* @return \Closure |
15
|
|
|
*/ |
16
|
|
View Code Duplication |
function add() |
|
|
|
|
17
|
|
|
{ |
18
|
|
|
return function ($a, $b) { |
19
|
23 |
|
if (!is_numeric($a)) { |
20
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $A must be numeric to perform addition, not %s', is_object($a) ? get_class($a) : gettype($a))); |
21
|
|
|
} |
22
|
18 |
|
if (!is_numeric($b)) { |
23
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $B must be numeric to perform addition, not %s', is_object($b) ? get_class($b) : gettype($b))); |
24
|
|
|
} |
25
|
13 |
|
return $a + $b; |
26
|
30 |
|
}; |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Returns a closure that subtracts one number from another |
31
|
|
|
* |
32
|
|
|
* @return \Closure |
33
|
|
|
*/ |
34
|
|
View Code Duplication |
function sub() |
|
|
|
|
35
|
|
|
{ |
36
|
|
|
return function ($a, $b) { |
37
|
19 |
|
if (!is_numeric($a)) { |
38
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $A must be numeric to perform subtraction, not %s', is_object($a) ? get_class($a) : gettype($a))); |
39
|
|
|
} |
40
|
14 |
|
if (!is_numeric($b)) { |
41
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $B must be numeric to perform subtraction, not %s', is_object($b) ? get_class($b) : gettype($b))); |
42
|
|
|
} |
43
|
9 |
|
return $a - $b; |
44
|
20 |
|
}; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Returns a closure that multiplies two numbers |
49
|
|
|
* |
50
|
|
|
* @return \Closure |
51
|
|
|
*/ |
52
|
|
View Code Duplication |
function mul() |
|
|
|
|
53
|
|
|
{ |
54
|
|
|
return function ($a, $b) { |
55
|
18 |
|
if (!is_numeric($a)) { |
56
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $A must be numeric to perform multiplication, not %s', is_object($a) ? get_class($a) : gettype($a))); |
57
|
|
|
} |
58
|
13 |
|
if (!is_numeric($b)) { |
59
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $B must be numeric to perform multiplication, not %s', is_object($b) ? get_class($b) : gettype($b))); |
60
|
|
|
} |
61
|
8 |
|
return $a * $b; |
62
|
18 |
|
}; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Returns a closure that returns the smallest of two numbers |
67
|
|
|
* |
68
|
|
|
* @return \Closure |
69
|
|
|
*/ |
70
|
|
View Code Duplication |
function min() |
|
|
|
|
71
|
|
|
{ |
72
|
|
|
return function ($a, $b) { |
73
|
18 |
|
if (!is_numeric($a)) { |
74
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $A must be numeric to determine minimum, not %s', is_object($a) ? get_class($a) : gettype($a))); |
75
|
|
|
} |
76
|
13 |
|
if (!is_numeric($b)) { |
77
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $B must be numeric to determine minimum, not %s', is_object($b) ? get_class($b) : gettype($b))); |
78
|
|
|
} |
79
|
8 |
|
return $a < $b ? $a : $b; |
80
|
18 |
|
}; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Returns a closure that returns the largest of two numbers |
85
|
|
|
* |
86
|
|
|
* @return \Closure |
87
|
|
|
*/ |
88
|
|
View Code Duplication |
function max() |
|
|
|
|
89
|
|
|
{ |
90
|
|
|
return function ($a, $b) { |
91
|
18 |
|
if (!is_numeric($a)) { |
92
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $A must be numeric to determine maximum, not %s', is_object($a) ? get_class($a) : gettype($a))); |
93
|
|
|
} |
94
|
13 |
|
if (!is_numeric($b)) { |
95
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $B must be numeric to determine maximum, not %s', is_object($b) ? get_class($b) : gettype($b))); |
96
|
|
|
} |
97
|
8 |
|
return $a < $b ? $b : $a; |
98
|
18 |
|
}; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Returns a closure that concatenates two strings using $glue |
103
|
|
|
* |
104
|
|
|
* @param string $glue |
105
|
|
|
* @return \Closure |
106
|
|
|
*/ |
107
|
|
|
function join($glue = '') |
108
|
|
|
{ |
109
|
22 |
|
if (!is_string($glue)) { |
110
|
5 |
|
throw new \InvalidArgumentException(sprintf('Argument $GLUE must be a string to join, not %s', is_object($glue) ? get_class($glue) : gettype($glue))); |
111
|
|
|
} |
112
|
|
|
return function ($a, $b) use ($glue) { |
113
|
17 |
|
if (!is_string($a)) { |
114
|
6 |
|
throw new \InvalidArgumentException(sprintf('Argument $A must be a string to join, not %s', is_object($a) ? get_class($a) : gettype($a))); |
115
|
|
|
} |
116
|
11 |
|
if (!is_string($b)) { |
117
|
6 |
|
throw new \InvalidArgumentException(sprintf('Argument $B must be a string to join, not %s', is_object($b) ? get_class($b) : gettype($b))); |
118
|
|
|
} |
119
|
5 |
|
return \join($glue, [$a, $b]); |
120
|
17 |
|
}; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Returns a closure that chains lists together |
125
|
|
|
* |
126
|
|
|
* > $lists = [[1, 2, 3], [4, 5, 6]] |
127
|
|
|
* > iterable($lists)->reduce(reductions\chain(), new ChainIterator()) |
128
|
|
|
* results in a ChainIterator: 1, 2, 3, 4, 5, 6 |
129
|
|
|
* |
130
|
|
|
* @return \Closure |
131
|
|
|
*/ |
132
|
|
|
function chain() |
133
|
|
|
{ |
134
|
|
|
return function ($chainIterator, $b) { |
135
|
4 |
|
if (!($chainIterator instanceof ChainIterator)) { |
136
|
1 |
|
throw new \InvalidArgumentException('Argument $A must be a ChainIterator. Did your call "reduce" with "new ChainIterator()" as the initial parameter?'); |
137
|
|
|
} |
138
|
|
|
|
139
|
3 |
|
$chainIterator->extend($b); |
140
|
3 |
|
return $chainIterator; |
141
|
5 |
|
}; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Returns a reduction closure |
146
|
|
|
* |
147
|
|
|
* @param string $name |
148
|
|
|
* @return \Closure |
149
|
|
|
* @throws \InvalidArgumentException |
150
|
|
|
* |
151
|
|
|
* @deprecated please use the reduction functions directly, will be removed in version 3.0 |
152
|
|
|
*/ |
153
|
|
|
function get_reduction($name) |
154
|
|
|
{ |
155
|
|
|
if (is_string($name)) { |
156
|
|
|
switch ($name) { |
157
|
|
|
case 'add': |
158
|
|
|
return add(); |
159
|
|
|
case 'sub': |
160
|
|
|
return sub(); |
161
|
|
|
case 'mul': |
162
|
|
|
return mul(); |
163
|
|
|
case 'min': |
164
|
|
|
return min(); |
165
|
|
|
case 'max': |
166
|
|
|
return max(); |
167
|
|
|
case 'join': |
168
|
|
|
return call_user_func_array('\Zicht\Itertools\reductions\join', array_slice(func_get_args(), 1)); |
169
|
|
|
case 'chain': |
170
|
|
|
return chain(); |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
throw new \InvalidArgumentException(sprintf('$NAME "%s" is not a valid reduction.', $name)); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @deprecated please use the reduction functions directly, will be removed in version 3.0 |
179
|
|
|
*/ |
180
|
|
|
function getReduction($name) |
|
|
|
|
181
|
|
|
{ |
182
|
|
|
return call_user_func_array('\Zicht\Itertools\reductions\get_reduction', func_get_args()); |
183
|
|
|
} |
184
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.