Completed
Push — master ( 5a66ad...309b32 )
by Amine
01:58
created

string.php ➔ chunks()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 55
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 30
nc 1
nop 0
dl 0
loc 55
rs 9.7692
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php namespace Tarsana\Functional;
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 18 and the first side effect is on line 150.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * This file contains some useful String functions.
4
 */
5
6
/**
7
 * Curried version of `explode()`.
8
 * ```php
9
 * $words = split(' ');
10
 * $words('Hello World'); // ['Hello', 'World']
11
 * ```
12
 *
13
 * @signature String -> String -> [String]
14
 * @param string $delimiter
0 ignored issues
show
Bug introduced by
There is no parameter named $delimiter. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
15
 * @param string $string
0 ignored issues
show
Bug introduced by
There is no parameter named $string. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
16
 * @return array
17
 */
18
function split() {
19
    return apply(curry('explode'), func_get_args());
20
}
21
22
/**
23
 * Curried version of `implode()`.
24
 * ```php
25
 * $sentence = join(' ');
26
 * $sentence(['Hello', 'World']); // 'Hello World'
27
 * ```
28
 *
29
 * @signature String -> [String] -> String
30
 * @param string $glue
0 ignored issues
show
Bug introduced by
There is no parameter named $glue. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
31
 * @param array $pieces
0 ignored issues
show
Bug introduced by
There is no parameter named $pieces. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
32
 * @return string
33
 */
34
function join() {
35
    return apply(curry(function($glue, $pieces){
36
        return implode($glue, $pieces);
37
    }), func_get_args());
38
}
39
40
/**
41
 * Curried version of `str_replace()`.
42
 * ```php
43
 * $string = 'a b c d e f';
44
 * $noSpace = replace(' ', '');
45
 * $noSpace($string); // 'abcdef'
46
 * replace(['a', 'b', ' '], '', $string) // 'cdef'
47
 * replace(['a', 'e', ' '], ['x', 'y', ''], $string); // 'xbcdyf'
48
 * ```
49
 *
50
 * @signature String|[String] -> String -> String|[String] -> String
51
 * @param  string $search
0 ignored issues
show
Bug introduced by
There is no parameter named $search. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
52
 * @param  string $replacement
0 ignored issues
show
Bug introduced by
There is no parameter named $replacement. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
53
 * @param  string $string
0 ignored issues
show
Bug introduced by
There is no parameter named $string. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
54
 * @return string
55
 */
56
function replace() {
57
    return apply(curry('str_replace'), func_get_args());
58
}
59
60
/**
61
 * Curried version of `preg_replace()`.
62
 * ```php
63
 * $string = 'A12;b_{F}|d';
64
 * $aplha = regReplace('/[^a-z]+/i', '');
65
 * $alpha($string); // 'AbFd'
66
 * ```
67
 *
68
 * @signature String -> String -> String -> String
69
 * @param  string $pattern
0 ignored issues
show
Bug introduced by
There is no parameter named $pattern. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
70
 * @param  string $replacement
0 ignored issues
show
Bug introduced by
There is no parameter named $replacement. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
71
 * @param  string $string
0 ignored issues
show
Bug introduced by
There is no parameter named $string. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
72
 * @return string
73
 */
74
function regReplace() {
75
    return apply(curry('preg_replace'), func_get_args());
76
}
77
78
/**
79
 * Alias of `strtoupper`.
80
 * ```php
81
 * upperCase('hello') // 'HELLO'
82
 * ```
83
 *
84
 * @signature String -> String
85
 * @param  string $string
86
 * @return string
87
 */
88
function upperCase($string) {
89
    return strtoupper($string);
90
}
91
92
/**
93
 * Alias of `strtolower`.
94
 * ```php
95
 * lowerCase('HELLO') // 'hello'
96
 * ```
97
 *
98
 * @signature String -> String
99
 * @param  string $string
100
 * @return string
101
 */
102
function lowerCase($string) {
103
    return strtolower($string);
104
}
105
106
/**
107
 * Gets the camlCase version of a string.
108
 * ```php
109
 * camelCase('Yes, we can! 123') // 'yesWeCan123'
110
 * ```
111
 *
112
 * @signature String -> String
113
 * @param  string $string
114
 * @return string
115
 */
116
function camelCase($string) {
117
    return apply(pipe(
118
        regReplace('/[^a-z0-9]+/i', ' '),
119
        'trim',
120
        'ucwords',
121
        replace(' ', ''),
122
        'lcfirst'
123
    ), [$string]);
124
}
125
126
/**
127
 * Gets the snake-case of the string using `$delimiter` as separator.
128
 * ```
129
 * $underscoreCase = snakeCase('_');
130
 * $underscoreCase('IAm-Happy'); // i_am_happy
131
 * ```
132
 *
133
 * @signature String -> String -> String
134
 * @param  string $delimiter
0 ignored issues
show
Bug introduced by
There is no parameter named $delimiter. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
135
 * @param  string $string
0 ignored issues
show
Bug introduced by
There is no parameter named $string. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
136
 * @return string
137
 */
138
function snakeCase() {
139
    $snackCase = function($delimiter, $string) {
140
        return apply(pipe(
141
            regReplace('/([A-Z])/', ' \\1'),
142
            regReplace('/([0-9]+)/', ' \\1'),
143
            regReplace('/[^a-z0-9]+/i', ' '),
144
            'trim',
145
            'strtolower',
146
            replace(' ', $delimiter)
147
        ), [$string]);
148
    };
149
    return apply(curry($snackCase), func_get_args());
150
};
151
152
/**
153
 * Checks if `$string` starts with `$token`.
154
 * ```php
155
 * $http = startsWith('http://');
156
 * $http('http://gitbub.com'); // true
157
 * $http('gitbub.com'); // false
158
 * ```
159
 *
160
 * @signature String -> String -> Boolean
161
 * @param  string $token
0 ignored issues
show
Bug introduced by
There is no parameter named $token. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
162
 * @param  string $string
0 ignored issues
show
Bug introduced by
There is no parameter named $string. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
163
 * @return bool
164
 */
165 View Code Duplication
function startsWith() {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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.

Loading history...
166
    $startsWith = function($token, $string) {
167
        return (
168
            strlen($token) <= strlen($string) &&
169
            substr($string, 0, strlen($token)) === $token
170
        );
171
    };
172
    return apply(curry($startsWith), func_get_args());
173
}
174
175
/**
176
 * Checks if `$string` ends with `$token`.
177
 * ```php
178
 * $dotCom = endsWith('.com');
179
 * $dotCom('http://gitbub.com'); // true
180
 * $dotCom('php.net'); // false
181
 * ```
182
 *
183
 * @signature String -> String -> Boolean
184
 * @param  string $token
0 ignored issues
show
Bug introduced by
There is no parameter named $token. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
185
 * @param  string $string
0 ignored issues
show
Bug introduced by
There is no parameter named $string. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
186
 * @return bool
187
 */
188 View Code Duplication
function endsWith() {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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.

Loading history...
189
    $endsWith = function($token, $string) {
190
        return (
191
            strlen($token) <= strlen($string) &&
192
            substr($string, - strlen($token)) === $token
193
        );
194
    };
195
    return apply(curry($endsWith), func_get_args());
196
}
197
198
/**
199
 * Checks if a string matches a regular expression.
200
 * ```php
201
 * $numeric = test('/^[0-9.]+$/');
202
 * $numeric('123.43'); // true
203
 * $numeric('12a3.43'); // false
204
 * ```
205
 *
206
 * @signature String -> String -> Boolean
207
 * @param  string $pattern
0 ignored issues
show
Bug introduced by
There is no parameter named $pattern. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
208
 * @param  string $string
0 ignored issues
show
Bug introduced by
There is no parameter named $string. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
209
 * @return bool
210
 */
211
function test() {
212
    $test = function($pattern, $string) {
213
        return 1 === preg_match($pattern, $string);
214
    };
215
    return apply(curry($test), func_get_args());
216
}
217
218
/**
219
 * Performs a global regular expression match
220
 * and returns array of results.
221
 * ```php
222
 * $numbers = match('/[0-9.]+/');
223
 * $numbers('Hello World'); // []
224
 * $numbers('12 is 4 times 3'); // ['12', '4', '3']
225
 * ```
226
 *
227
 * @signature String -> String -> [String]
228
 * @param  string $pattern
0 ignored issues
show
Bug introduced by
There is no parameter named $pattern. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
229
 * @param  string $string
0 ignored issues
show
Bug introduced by
There is no parameter named $string. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
230
 * @return array
231
 */
232
function match() {
233
    $match = function($pattern, $string) {
234
        $results = [];
235
        preg_match_all($pattern, $string, $results);
236
        return $results[0];
237
    };
238
    return apply(curry($match), func_get_args());
239
}
240
241
/**
242
 * Curried version of `substr_count` with changed order of parameters,
243
 * ```php
244
 * $spaces = occurences(' ');
245
 * $spaces('Hello') // 0
246
 * $spaces('12 is 4 times 3'); // 4
247
 * ```
248
 *
249
 * @signature String -> String -> Number
250
 * @param  string $token
0 ignored issues
show
Bug introduced by
There is no parameter named $token. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
251
 * @param  string $text
0 ignored issues
show
Bug introduced by
There is no parameter named $text. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
252
 * @return int
253
 */
254
function occurences() {
255
    $occurences = function($token, $text) {
256
        return substr_count($text, $token);
257
    };
258
    return apply(curry($occurences), func_get_args());
259
}
260
261
/**
262
 * Splits a string into chunks without spliting any group surrounded with some
263
 * specified characters. `$surrounders` is a string where each pair of characters
264
 * specifies the starting and ending characters of a group that should not be split.
265
 * ```php
266
 * $groups = chunks('(){}', ',');
267
 * $groups('1,2,(3,4,5),{6,(7,8)},9'); // ['1', '2', '(3,4,5)', '{6,(7,8)}', '9']
268
 *
269
 * $names = chunks('()""', ' ');
270
 * $names('Foo "Bar Baz" (Some other name)'); // ['Foo', 'Bar Baz', 'Some other name']
271
 * ```
272
 *
273
 * @signature String -> String -> String -> [String]
274
 * @param  string $surrounders
0 ignored issues
show
Bug introduced by
There is no parameter named $surrounders. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
275
 * @param  string $separator
0 ignored issues
show
Bug introduced by
There is no parameter named $separator. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
276
 * @param  sring $text
0 ignored issues
show
Bug introduced by
There is no parameter named $text. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
277
 * @return array
278
 */
279
function chunks() {
280
    $chunks = function($surrounders, $separator, $text) {
281
        // Let's assume some values to understand how this function works
282
        // surrounders = '""{}()'
283
        // separator = ' '
284
        // $text = 'foo ("bar baz" alpha) beta'
285
286
        $surrounders = map(slices(1), slices(2, $surrounders)); // [['"'. '"'], ['{'. '}'], ['(', ')']]
0 ignored issues
show
Unused Code Comprehensibility introduced by
68% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
287
        $openings = map(get(0), $surrounders); // ['"', '{', '(']
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
288
        $closings = map(get(1), $surrounders); // ['"', '}', ')']
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
289
        $numOfSurrounders = length($surrounders); // 3
290
        $indexes = keys($surrounders); // [0, 1, 2]
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
291
292
        $items = split($separator, $text); // ['foo', '("bar', 'baz"', 'alpha)', 'beta']
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
293
294
        // The initial state
295
        $state = (object) [
296
            'chunks'    => [], //: the resulting chunks
297
            'counts'   => array_fill(0, $numOfSurrounders, 0), // [0, 0, 0] : count of openings not closed yet
298
            'total'    => 0 //: total of not closed openings
299
        ];
300
        // We will iterate over $items and update the $state while adding them
301
        // For each item we need to update counts and chunks
302
303
        // Updates count for a single surrender (the surrender at $index)
304
        // $item : the item we are adding
305
        // $counts : the previous counts
306
        $updateCountAt = curry(function($item, $counts, $index) use($openings, $closings) {
307
            $count = occurences(__(), $item);
308
            return ($openings[$index] == $closings[$index]) ?
309
                ($counts[$index] + $count($openings[$index])) % 2 :
310
                $counts[$index] + $count($openings[$index]) - $count($closings[$index]);
311
        });
312
        // Updates counts for all surrenders
313
        $updateCounts = curry(function($item, $counts) use($indexes, $updateCountAt) {
314
            return map($updateCountAt($item, $counts), $indexes);
315
        });
316
        // Adds an item to the state and returns a new state
317
        $addItem = function($state, $item) use ($separator, $updateCounts){
318
            $counts = $updateCounts($item, get('counts', $state));
319
            $newChunks = (0 == $state->total) // if all openings are closed
320
                ? append($item, $state->chunks) // then add a new chunk
321
                // else append the item to the last chunk using the separator as glue
322
                : append(last($state->chunks) . $separator . $item, init($state->chunks));
323
            return (object) [
324
                'chunks' => $newChunks,
325
                'counts' => $counts,
326
                'total' => sum($counts)
327
            ];
328
        };
329
        // Returns the chunks of the resulting state after adding all items
330
        return get('chunks', reduce($addItem, $state, $items));
331
    };
332
    return apply(curry($chunks), func_get_args());
333
}
334