Passed
Push — master ( 65ca3f...66b084 )
by Radosław
02:04
created

Phln   F

Complexity

Total Complexity 102

Size/Duplication

Total Lines 1924
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 207
dl 0
loc 1924
rs 2
c 0
b 0
f 0
wmc 102

How to fix   Complexity   

Complex Class

Complex classes like Phln often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Phln, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types=1);
3
4
// Static wrapper for all phln functions/consts
5
// DO NOT EDIT THIS FILE
6
// it was generated by create:bundle command
7
8
namespace phln;
9
10
class Phln
11
{
12
    const all = \phln\collection\all;
13
    const any = \phln\collection\any;
14
    const append = \phln\collection\append;
15
    const chunk = \phln\collection\chunk;
16
    const collapse = \phln\collection\collapse;
17
    const concat = \phln\collection\concat;
18
    const contains = \phln\collection\contains;
19
    const filter = \phln\collection\filter;
20
    const find = \phln\collection\find;
21
    const flatMap = \phln\collection\flatMap;
22
    const fromPairs = \phln\collection\fromPairs;
23
    const head = \phln\collection\head;
24
    const init = \phln\collection\init;
25
    const join = \phln\collection\join;
26
    const last = \phln\collection\last;
27
    const length = \phln\collection\length;
28
    const map = \phln\collection\map;
29
    const mapIndexed = \phln\collection\mapIndexed;
30
    const none = \phln\collection\none;
31
    const nth = \phln\collection\nth;
32
    const pluck = \phln\collection\pluck;
33
    const prepend = \phln\collection\prepend;
34
    const range = \phln\collection\range;
35
    const reduce = \phln\collection\reduce;
36
    const reject = \phln\collection\reject;
37
    const reverse = \phln\collection\reverse;
38
    const slice = \phln\collection\slice;
39
    const sort = \phln\collection\sort;
40
    const sortBy = \phln\collection\sortBy;
41
    const tail = \phln\collection\tail;
42
    const unique = \phln\collection\unique;
43
    const F = \phln\fn\F;
44
    const T = \phln\fn\T;
45
    const otherwise = \phln\fn\otherwise;
46
    const always = \phln\fn\always;
47
    const apply = \phln\fn\apply;
48
    const arity = \phln\fn\arity;
49
    const compose = \phln\fn\compose;
50
    const curry = \phln\fn\curry;
51
    const curryN = \phln\fn\curryN;
52
    const identity = \phln\fn\identity;
53
    const negate = \phln\fn\negate;
54
    const of = \phln\fn\of;
55
    const once = \phln\fn\once;
56
    const __ = \phln\fn\__;
57
    const partial = \phln\fn\partial;
58
    const partialRight = \phln\fn\partialRight;
59
    const pipe = \phln\fn\pipe;
60
    const swap = \phln\fn\swap;
61
    const tap = \phln\fn\tap;
62
    const throwException = \phln\fn\throwException;
63
    const unapply = \phln\fn\unapply;
64
    const allPass = \phln\logic\allPass;
65
    const both = \phln\logic\both;
66
    const cond = \phln\logic\cond;
67
    const defaultTo = \phln\logic\defaultTo;
68
    const either = \phln\logic\either;
69
    const ifElse = \phln\logic\ifElse;
70
    const isEmpty = \phln\logic\isEmpty;
71
    const not = \phln\logic\not;
72
    const add = \phln\math\add;
73
    const dec = \phln\math\dec;
74
    const divide = \phln\math\divide;
75
    const inc = \phln\math\inc;
76
    const mean = \phln\math\mean;
77
    const median = \phln\math\median;
78
    const modulo = \phln\math\modulo;
79
    const multiply = \phln\math\multiply;
80
    const product = \phln\math\product;
81
    const subtract = \phln\math\subtract;
82
    const sum = \phln\math\sum;
83
    const eqProps = \phln\object\eqProps;
84
    const keys = \phln\object\keys;
85
    const merge = \phln\object\merge;
86
    const objOf = \phln\object\objOf;
87
    const omit = \phln\object\omit;
88
    const path = \phln\object\path;
89
    const pathOr = \phln\object\pathOr;
90
    const pick = \phln\object\pick;
91
    const prop = \phln\object\prop;
92
    const props = \phln\object\props;
93
    const toPairs = \phln\object\toPairs;
94
    const values = \phln\object\values;
95
    const where = \phln\object\where;
96
    const whereEq = \phln\object\whereEq;
97
    const clamp = \phln\relation\clamp;
98
    const difference = \phln\relation\difference;
99
    const equals = \phln\relation\equals;
100
    const gt = \phln\relation\gt;
101
    const gte = \phln\relation\gte;
102
    const intersection = \phln\relation\intersection;
103
    const lt = \phln\relation\lt;
104
    const lte = \phln\relation\lte;
105
    const max = \phln\relation\max;
106
    const min = \phln\relation\min;
107
    const pathEq = \phln\relation\pathEq;
108
    const propEq = \phln\relation\propEq;
109
    const match = \phln\string\match;
110
    const regexp = \phln\string\regexp;
111
    const replace = \phln\string\replace;
112
    const split = \phln\string\split;
113
    const test = \phln\string\test;
114
    const is = \phln\type\is;
115
    const typeCond = \phln\type\typeCond;
116
117
    /**
118
     * Returns `true` if all elements of array match the predicate, `false` otherwise.
119
     *
120
     * @phlnSignature (a -> Boolean) -> [a] -> Boolean
121
     * @phlnCategory collection
122
     * @param callable $predicate
123
     * @param array $list
124
     * @return \Closure|bool
125
     * @example
126
     *      $onlyTwos = P::all(P::equals(2));
127
     *      $onlyTwos([1, 2, 2]); // false
128
     */
129
    public static function all(callable $predicate = NULL, array $list = [])
130
    {
131
        return \phln\collection\all(...func_get_args());
132
    }
133
134
    /**
135
     * Returns `true` if at least one of array elements match the predicate, `false` otherwise.
136
     *
137
     * @phlnSignature (a -> Boolean) -> [a] -> Boolean
138
     * @phlnCategory collection
139
     * @param callable $predicate
140
     * @param array $list
141
     * @return \Closure|bool
142
     * @example
143
     *      $hasTwos = P::any(P::equals(2));
144
     *      $hasTwos([1, 2, 3, 4]); // true
145
     */
146
    public static function any(callable $predicate = NULL, array $list = [])
147
    {
148
        return \phln\collection\any(...func_get_args());
149
    }
150
151
    /**
152
     * Returns a new list containing the contents of the given list or string, followed by the given element.
153
     *
154
     * @phlnSignature a -> [a] -> [a]
155
     * @phlnSignature String -> String -> String
156
     * @phlnCategory collection
157
     * @param mixed $value
158
     * @param array|string $collection
159
     * @return \Closure|string|array
160
     * @example
161
     *      P::append(3, [1, 2]); // [1, 2, 3]
162
     *      P::append([3], [1, 2]); // [1, 2, [3]]
163
     *      P::append('foo', 'bar'); // 'barfoo'
164
     */
165
    public static function append($value = NULL, $collection = NULL)
166
    {
167
        return \phln\collection\append(...func_get_args());
168
    }
169
170
    /**
171
     * Chunks an array or string into arrays with `size` elements.
172
     * The last chunk may contain less than `size` elements.
173
     *
174
     * @phlnSignature Number -> [a] -> [[a]]
175
     * @phlnSignature Number -> String -> [String]
176
     * @phlnCategory collection
177
     * @param integer $size
178
     * @param array|string $collection
179
     * @return \Closure|array
180
     * @example
181
     *      P::chunk(2, [1, 2, 3, 4]); // [[1, 2], [3, 4]]
182
     *      P::chunk(2, 'hello'); // ['he', 'll', 'o']
183
     */
184
    public static function chunk(int $size = 0, $collection = NULL)
185
    {
186
        return \phln\collection\chunk(...func_get_args());
187
    }
188
189
    /**
190
     * Flattens array elements by one level
191
     *
192
     * @phlnSignature [[*], [*]] -> [*, *]
193
     * @phlnCategory collection
194
     * @param array $list
195
     * @return array
196
     */
197
    public static function collapse(array $list): array
198
    {
199
        return \phln\collection\collapse(...func_get_args());
200
    }
201
202
    /**
203
     * Returns the result of concatenating the given lists or strings.
204
     *
205
     * Note: `P::concat` expects both arguments to be of the same type, otherwise it will throw an exception.
206
     *
207
     * @phlnSignature [a] -> [a] -> [a]
208
     * @phlnSignature String -> String -> String
209
     * @phlnCategory collection
210
     * @param string|array $a
211
     * @param string|array $b
212
     * @return \Closure|string|array
213
     * @throws \InvalidArgumentException
214
     * @example
215
     *      P::concat([1, 2], [3]); // [1, 2, 3]
216
     *      P::concat('foo', 'bar'); // 'foobar'
217
     */
218
    public static function concat($a = NULL, $b = NULL)
219
    {
220
        return \phln\collection\concat(...func_get_args());
221
    }
222
223
    /**
224
     * Returns `true` if the specified value is equal, `P::equals` terms,
225
     * to at least one element of the given collection; `false` otherwise.
226
     *
227
     * @phlnSignature a -> [a] -> Boolean
228
     * @phlnSignature String -> String -> Boolean
229
     * @phlnCategory collection
230
     * @param mixed $value
231
     * @param array|string $collection
232
     * @return \Closure|bool
233
     * @example
234
     *      P::contains(1, [1, 2, 3]); // true
235
     *      P::contains('foo', 'foobar'); // true
236
     */
237
    public static function contains($value = NULL, $collection = NULL)
238
    {
239
        return \phln\collection\contains(...func_get_args());
240
    }
241
242
    /**
243
     * Filters elements of an array using a callback function
244
     *
245
     * @phlnSignature (a -> Boolean) -> [a] -> Boolean
246
     * @phlnCategory collection
247
     * @param callable $predicate
248
     * @param array $list
249
     * @return \Closure|mixed
250
     * @example
251
     *      P::filter(equals(1), [1, 2, 3]); // [1]
252
     */
253
    public static function filter(callable $predicate = NULL, array $list = [])
254
    {
255
        return \phln\collection\filter(...func_get_args());
256
    }
257
258
    /**
259
     * Returns the first element of the list which matches the predicate,
260
     * or `null` if no element matches.
261
     *
262
     * @phlnSignature (a -> Boolean) -> [a] -> a
263
     * @phlnCategory collection
264
     * @param callable $predicate
265
     * @param array $list
266
     * @return \Closure|mixed
267
     * @example
268
     *      $xs = [['a' => 1], ['a' => 2], ['a' => 3]];
269
     *      P::find(equals(['a' => 1]), $xs); // ['a' => 1]
270
     */
271
    public static function find(callable $predicate = NULL, array $list = [])
272
    {
273
        return \phln\collection\find(...func_get_args());
274
    }
275
276
    /**
277
     * Maps a function over list and concatenates results
278
     *
279
     * @phlnSignature (a -> b) -> [a] -> [b]
280
     * @phlnCategory collection
281
     * @param callable $mapper
282
     * @param array $list
283
     * @return \Closure|mixed
284
     * @example
285
     *      $duplicateElements = P::flatMap(function ($i) {
286
     *          return [$i, $i];
287
     *      });
288
     *
289
     *      $duplicateElements([1, 2]); // [1, 1, 2, 2]
290
     */
291
    public static function flatMap(callable $mapper = NULL, array $list = [])
292
    {
293
        return \phln\collection\flatMap(...func_get_args());
294
    }
295
296
    /**
297
     * Creates a new key => value object from list of pairs.
298
     *
299
     * @phlnSignature [[k, v]] -> {k: v}
300
     * @phlnCategory collection
301
     * @param array $pairs
302
     * @return array
303
     * @example
304
     *      P::fromPairs([['foo', 1], ['bar', 2]]); // [ 'foo' => 1, 'bar' => 2 ]
305
     */
306
    public static function fromPairs(array $pairs): array
307
    {
308
        return \phln\collection\fromPairs(...func_get_args());
309
    }
310
311
    /**
312
     * Returns the first element of a given list or string
313
     *
314
     * @phlnSignature [a] -> a | Null
315
     * @phlnSignature String -> String
316
     * @phlnCategory collection
317
     * @param array $collection
318
     * @return mixed|null
319
     * @example
320
     *      P::head([1, 2, 3]); // 1
321
     *      P::head([]); // null
322
     *      P::head('foo'); // 'f'
323
     *      P::head('f'); // ''
324
     */
325
    public static function head($collection)
326
    {
327
        return \phln\collection\head(...func_get_args());
328
    }
329
330
    /**
331
     * Returns all but the last element of the given array or string.
332
     *
333
     * @phlnSignature [a] -> [a]
334
     * @phlnSignature String -> String
335
     * @phlnCategory collection
336
     * @param array|string $collection
337
     * @return array|string
338
     * @example
339
     *      P::init([1, 2, 3]); // [1, 2]
340
     *      P::init([1, 2]); // [1]
341
     *      P::init([1]); // []
342
     *      P::init([]); // []
343
     *
344
     *      P::init('lorem'); // 'lore'
345
     *      P::init('lo'); // 'l'
346
     *      P::init('l'); // ''
347
     *      P::init(''); // ''
348
     */
349
    public static function init($collection)
350
    {
351
        return \phln\collection\init(...func_get_args());
352
    }
353
354
    /**
355
     * Returns a string made by inserting the separator between each element and concatenating all the elements into a single string.
356
     *
357
     * @phlnSignature String -> [a] -> String
358
     * @phlnCategory collection
359
     * @param string $separator
360
     * @param array $list
361
     * @return \Closure|mixed
362
     * @example
363
     *      $spacer = P::join(' ');
364
     *      $spacer([1, 2, 3]); // '1 2 3'
365
     */
366
    public static function join(string $separator = '', array $list = [])
367
    {
368
        return \phln\collection\join(...func_get_args());
369
    }
370
371
    /**
372
     * Returns the last element of the given list or string.
373
     *
374
     * @phlnSignature [a] -> a
375
     * @phlnSignature String -> String
376
     * @phlnCategory collection
377
     * @param array|string $list
378
     * @return mixed|null
379
     * @example
380
     *      P::last([1, 2, 3]); // 3
381
     *      P::last([]); // null
382
     *      P::last('foo'); // 'o'
383
     *      P::last('f'); // 'f'
384
     */
385
    public static function last($list)
386
    {
387
        return \phln\collection\last(...func_get_args());
388
    }
389
390
    /**
391
     * Returns the number of elements in the array or string
392
     *
393
     * @phlnSignature [a] -> Number
394
     * @phlnSignature String -> Number
395
     * @phlnCategory collection
396
     * @param string|array $collection
397
     * @return int
398
     * @example
399
     *      P::length('lorem'); // 5
400
     */
401
    public static function length($collection): int
402
    {
403
        return \phln\collection\length(...func_get_args());
404
    }
405
406
    /**
407
     * Applies the callback to the elements of the given arrays
408
     *
409
     * @phlnSignature (a -> b) -> [a] -> [b]
410
     * @phlnCategory collection
411
     * @param callable $fn
412
     * @param array $list
413
     * @return \Closure|array
414
     */
415
    public static function map(callable $fn = NULL, array $list = [])
416
    {
417
        return \phln\collection\map(...func_get_args());
418
    }
419
420
    /**
421
     * Applies the callback to the elements of the given arrays
422
     *
423
     * Callback will receive index of iterated value as a second argument.
424
     *
425
     * @phlnSignature ((a, i) -> b) -> [a] -> [b]
426
     * @phlnCategory collection
427
     * @param callable $fn
428
     * @param array $list
429
     * @return \Closure|array
430
     */
431
    public static function mapIndexed(callable $fn = NULL, array $list = [])
432
    {
433
        return \phln\collection\mapIndexed(...func_get_args());
434
    }
435
436
    /**
437
     * Returns `true` if no elements of the list match the predicate, `false` otherwise.
438
     *
439
     * @phlnSignature (a -> Boolean) -> [a] -> Boolean
440
     * @phlnCategory collection
441
     * @param callable $predicate
442
     * @param array $list
443
     * @return \Closure|mixed
444
     * @example
445
     *      $isEven = function ($i) {
446
     *          return $i % 2 === 0;
447
     *      };
448
     *
449
     *      P::none($isEven, [1, 3, 5]); // true
450
     *      P::none($isEven, [1, 3, 5, 6]); // false
451
     */
452
    public static function none(callable $predicate = NULL, array $list = [])
453
    {
454
        return \phln\collection\none(...func_get_args());
455
    }
456
457
    /**
458
     * Returns the nth element of the given list or string.
459
     * If n is negative the element at index length - n is returned.
460
     *
461
     * @phlnSignature Number -> [a] -> a | Null
462
     * @phlnCategory collection
463
     * @param integer $n
464
     * @param array $list
465
     * @return \Closure|mixed
466
     * @example
467
     *      P::nth(1, [1, 2, 3]); // 2
468
     *      P::nth(-1, [1, 2, 3]); // 3
469
     */
470
    public static function nth(int $n = 0, array $list = [])
471
    {
472
        return \phln\collection\nth(...func_get_args());
473
    }
474
475
    /**
476
     * Returns a new list by plucking the same named property off all objects in the list supplied.
477
     *
478
     * @phlnSignature k -> [{k: v}] -> v
479
     * @phlnCategory collection
480
     * @param string|integer $key
481
     * @param array $list
482
     * @return \Closure|array
483
     * @example
484
     *      $list = [['a' => 1], ['a' => 2]];
485
     *      P::pluck('a', $list); // [1, 2]
486
     */
487
    public static function pluck($key = '', array $list = [])
488
    {
489
        return \phln\collection\pluck(...func_get_args());
490
    }
491
492
    /**
493
     * Returns a new collection with the given element at the front, followed by the contents of the list or string.
494
     *
495
     * @phlnSignature a -> [a] -> [a]
496
     * @phlnSignature String -> String -> String
497
     * @phlnCategory collection
498
     * @param mixed $value
499
     * @param string|array $collection
500
     * @return \Closure|array
501
     * @example
502
     *      P::prepend(3, [1, 2]); // [3, 1, 2]
503
     *      P::prepend([3], [1, 2]); // [[3], 1, 2]
504
     *      P::prepend('foo', 'bar'); // [[3], 1, 2]
505
     */
506
    public static function prepend($value = NULL, $collection = NULL)
507
    {
508
        return \phln\collection\prepend(...func_get_args());
509
    }
510
511
    /**
512
     * Returns a list of numbers from `from` (inclusive) to `to` (exclusive).
513
     *
514
     * @phlnSignature Integer a => a -> a -> [a]
515
     * @phlnCategory collection
516
     * @param int $start
517
     * @param int $end
518
     * @return \Closure|array
519
     * @example
520
     *      P::range(0, 3); // [0, 1, 2]
521
     */
522
    public static function range(int $start = 0, int $end = 0)
523
    {
524
        return \phln\collection\range(...func_get_args());
525
    }
526
527
    /**
528
     * Returns a single item by iterating through the list, successively calling the iterator function and passing it an accumulator value and the current value from the array, and then passing the result to the next call.
529
     *
530
     * The iterator function receives two values: (`acc`, `value`).
531
     *
532
     * @phlnSignature ((a, b) -> a) -> a -> [b] -> a
533
     * @phlnCategory collection
534
     * @param callable $reducer
535
     * @param mixed $initialValue
536
     * @param array $list
537
     * @return \Closure|mixed
538
     * @example
539
     *      P::reduce(P::subtract, 0, [1, 2, 3, 4]);
540
     *      // ((((0 - 1) - 2) - 3) - 4) => -10
541
     */
542
    public static function reduce(callable $reducer = NULL, $initialValue = NULL, array $list = [])
543
    {
544
        return \phln\collection\reduce(...func_get_args());
545
    }
546
547
    /**
548
     * The negation of `filter`.
549
     *
550
     * @phlnSignature (a -> Boolean) -> [a] -> [a]
551
     * @phlnCategory collection
552
     * @param callable $predicate
553
     * @param array $list
554
     * @return \Closure|array
555
     * @example
556
     *      $isOdd = function ($i) {
557
     *          return $i % 2 === 1;
558
     *      };
559
     *      P::reject($isOdd, [1, 2, 3, 4]); // [2, 4]
560
     */
561
    public static function reject(callable $predicate = NULL, array $list = [])
562
    {
563
        return \phln\collection\reject(...func_get_args());
564
    }
565
566
    /**
567
     * Returns a new list or string with the elements in reverse order.
568
     *
569
     * @phlnSignature [a] -> [a]
570
     * @phlnSignature String -> String
571
     * @phlnCategory collection
572
     * @param array|string $collection
573
     * @return array|string
574
     * @see \array_reverse()
575
     * @see \strrev()
576
     * @example
577
     *      P::reverse([1, 2, 3]); // [3, 2, 1]
578
     *      P::reverse('foo'); // 'oof'
579
     */
580
    public static function reverse($collection)
581
    {
582
        return \phln\collection\reverse(...func_get_args());
583
    }
584
585
    /**
586
     * Extracts a slice of the array or string
587
     *
588
     * @phlnSignature Integer -> Integer -> [a] -> [a]
589
     * @phlnSignature Integer -> Integer -> String -> String
590
     * @phlnCategory collection
591
     * @param integer $offset
592
     * @param integer $length
593
     * @param string|array $collection
594
     * @return \Closure|array|string
595
     * @see \array_slice()
596
     * @see \substr()
597
     * @example
598
     *      $takeTwo = P::slice(0, 2);
599
     *      $takeTwo([1, 2, 3]); // [1, 2]
600
     */
601
    public static function slice(int $offset = 0, int $length = 0, $collection = NULL)
602
    {
603
        return \phln\collection\slice(...func_get_args());
604
    }
605
606
    /**
607
     * Returns a copy of the list, sorted according to the comparator function, which should accept two values at a time and return a negative number if the first value is smaller, a positive number if it's larger, and zero if they are equal.
608
     *
609
     * @phlnSignature ((a, a) -> Number) -> [a] -> [a]
610
     * @phlnCategory collection
611
     * @param callable $comparator
612
     * @param array $list
613
     * @return \Closure|array
614
     * @see \usort()
615
     * @example
616
     *      $diff = function ($a, $b) {
617
     *          return $a - $b;
618
     *      };
619
     *
620
     *      P::sort($diff, [3, 2, 1]); // [1, 2, 3]
621
     */
622
    public static function sort(callable $comparator = NULL, array $list = [])
623
    {
624
        return \phln\collection\sort(...func_get_args());
625
    }
626
627
    /**
628
     * Sorts the list according to the supplied function.
629
     *
630
     * @phlnSignature (a -> b) -> [a] -> [a]
631
     * @phlnCategory collection
632
     * @param callable $mapper
633
     * @param array $list
634
     * @return \Closure|array
635
     * @see \array_multisort()
636
     * @example
637
     *      $alice = ['name' => 'alice'];
638
     *      $bob = ['name' => 'bob'];
639
     *      $clara = ['name' => 'clara'];
640
     *      $people = [$bob, $clara, $alice];
641
     *
642
     *      P::soryBy(P::prop('name'), $people); // [$alice, $bob, $clara]
643
     */
644
    public static function sortBy(callable $mapper = NULL, array $list = [])
645
    {
646
        return \phln\collection\sortBy(...func_get_args());
647
    }
648
649
    /**
650
     * Returns all but the first element of the given array or string
651
     *
652
     * @phlnSignature [a] -> [a]
653
     * @phlnSignature String -> String
654
     * @phlnCategory collection
655
     * @param array $collection
656
     * @return array
657
     * @example
658
     *      P::tail([1, 2, 3]); // [2, 3]
659
     *      P::tail([1]); // []
660
     *      P::tail([]); // []
661
     *      P::tail('lorem'); // 'orem'
662
     *      P::tail('l'); // ''
663
     *      P::tail(''); // ''
664
     */
665
    public static function tail($collection)
666
    {
667
        return \phln\collection\tail(...func_get_args());
668
    }
669
670
    /**
671
     * Returns a new list containing only one copy of each element in the original list. Strict comparision is used to determine equality.
672
     *
673
     * @phlnSignature [a] -> [a]
674
     * @phlnCategory collection
675
     * @param array $list
676
     * @return array
677
     * @example
678
     *      P::unique([3, 2, 1, 1, 3, 2]); // [3, 2, 1]
679
     */
680
    public static function unique(array $list): array
681
    {
682
        return \phln\collection\unique(...func_get_args());
683
    }
684
685
    /**
686
     * A function that always returns `false`. Any passed in parameters are ignored.
687
     *
688
     * @phlnSignature * -> Boolean
689
     * @phlnCategory function
690
     * @return bool
691
     */
692
    public static function F(): bool
693
    {
694
        return \phln\fn\F(...func_get_args());
695
    }
696
697
    /**
698
     * A function that always returns `true`. Any passed in parameters are ignored.
699
     *
700
     * @phlnSignature * -> Boolean
701
     * @phlnCategory function
702
     * @return bool
703
     */
704
    public static function T(): bool
705
    {
706
        return \phln\fn\T(...func_get_args());
707
    }
708
709
    /**
710
     * Returns a function that always returns the given value.
711
     * For non-primitives the value returned is a reference to the original value.
712
     *
713
     * @phlnSignature a -> (* -> a)
714
     * @phlnCategory function
715
     * @param $value
716
     * @return \Closure
717
     * @example
718
     *      $foo = P::always('foo');
719
     *      $foo(); // 'foo'
720
     */
721
    public static function always($value): \Closure
722
    {
723
        return \phln\fn\always(...func_get_args());
724
    }
725
726
    /**
727
     * Applies function `fn` to the argument list. This is useful for creating a fixed-arity function from a variadic function.
728
     *
729
     * @phlnSignature (*... -> a) -> [*] -> a
730
     * @phlnCategory function
731
     * @param callable $fn
732
     * @param array $arguments
733
     * @return \Closure|mixed
734
     * @example
735
     *      P::apply(P::sum, [1, 2]); // 3
736
     */
737
    public static function apply(callable $fn = NULL, array $arguments = [])
738
    {
739
        return \phln\fn\apply(...func_get_args());
740
    }
741
742
    /**
743
     * Takes a function and returns its arity.
744
     *
745
     * @phlnSignature (*... -> *) -> Number
746
     * @phlnCategory function
747
     * @param callable $fn
748
     * @return int
749
     * @example
750
     *      P::arity('var_dump'); // 1
751
     */
752
    public static function arity(callable $fn): int
753
    {
754
        return \phln\fn\arity(...func_get_args());
755
    }
756
757
    /**
758
     * Performs left-to-right function composition.
759
     * The leftmost function may have any arity; the remaining functions must be unary.
760
     *
761
     * **Note**: The result of pipe is not automatically curried.
762
     *
763
     * @phlnSignature [((a, b, ..., n) -> o), (o -> p), ..., (x -> y), (y -> z)] -> (a, b, ..., n) -> z)
764
     * @phlnCategory function
765
     * @param callable[] ...$fns
766
     * @return \Closure
767
     * @throws \UnderflowException
768
     */
769
    public static function compose(array $fns): \Closure
770
    {
771
        return \phln\fn\compose(...func_get_args());
772
    }
773
774
    /**
775
     * Returns a curried equivalent of the provided function.
776
     *
777
     * Curried function doesn't require providing arguments one at a time.
778
     * If `f` is a ternary function and `g` is `P::curry(f)`, the following are equivalent.
779
     *      * g(1)(2)(3)
780
     *      * g(1)(2, 3)
781
     *      * g(1, 2)(3)
782
     *      * g(1, 2, 3)
783
     *
784
     * @phlnSignature (* → a) → (* → a)
785
     * @phlnCategory function
786
     * @param callable $fn
787
     * @param array $args
788
     * @return \Closure|mixed
789
     */
790
    public static function curry(callable $fn, array $args = [])
791
    {
792
        return \phln\fn\curry(...func_get_args());
793
    }
794
795
    /**
796
     * Returns a curried equivalent of the provided function, with the specified arity.
797
     *
798
     * Curried function doesn't require providing arguments one at a time.
799
     * If `f` is a ternary function and `g` is `P::curryN(3, f)`, the following are equivalent.
800
     *      * g(1)(2)(3)
801
     *      * g(1)(2, 3)
802
     *      * g(1, 2)(3)
803
     *      * g(1, 2, 3)
804
     *
805
     * @phlnSignature Number -> (* → a) → (* → a)
806
     * @phlnCategory function
807
     * @param int $n
808
     * @param callable $fn
809
     * @param array $args
810
     * @return \Closure|mixed
811
     */
812
    public static function curryN(int $n, callable $fn, array $args = [])
813
    {
814
        return \phln\fn\curryN(...func_get_args());
815
    }
816
817
    /**
818
     * A function that does nothing but return the parameter supplied to it. Good as a default or placeholder function.
819
     *
820
     * @phlnSignature a -> a
821
     * @phlnCategory function
822
     * @param $value
823
     * @return mixed
824
     * @example
825
     *      P::identity(1) === 1; // 'true'
826
     */
827
    public static function identity($value)
828
    {
829
        return \phln\fn\identity(...func_get_args());
830
    }
831
832
    /**
833
     * Creates a function that negates the result of the predicate.
834
     *
835
     * @phlnSignature (*... -> *) -> (*... -> Boolean)
836
     * @phlnCategory function
837
     * @param callable $predicate
838
     * @return \Closure
839
     * @example
840
     *      $isEven = function ($i) {
841
     *          return $i % 2 === 0;
842
     *      };
843
     *
844
     *      P::filter(P::negate($isEven), [1, 2, 3, 4, 5, 6]); // [1, 3, 5]
845
     */
846
    public static function negate(callable $predicate): \Closure
847
    {
848
        return \phln\fn\negate(...func_get_args());
849
    }
850
851
    /**
852
     * Returns a singleton array containing the value provided.
853
     *
854
     * @phlnSignature a -> [a]
855
     * @phlnCategory function
856
     * @param mixed $value
857
     * @return array
858
     * @example
859
     *      P::of(null); // [null]
860
     *      P::of('a'); // ['a']
861
     */
862
    public static function of($value): array
863
    {
864
        return \phln\fn\of(...func_get_args());
865
    }
866
867
    /**
868
     * Accepts a function `fn` and returns a function that guards invocation of `fn` such that `fn` can only ever be called once, no matter how many times the returned function is invoked. The first value calculated is returned in subsequent invocations.
869
     *
870
     * @phlnSignature (a... -> b) -> (a... -> b)
871
     * @phlnCategory function
872
     * @param callable $fn
873
     * @return \Closure
874
     * @example
875
     *      $f = P::once('\rand');
876
     *      $f(1, 100); // 4
877
     *      $f(1, 100); // 4
878
     *      $f(1, 100); // 4
879
     */
880
    public static function once(callable $fn): \Closure
881
    {
882
        return \phln\fn\once(...func_get_args());
883
    }
884
885
    /**
886
     * Takes a function `f` and a list of arguments, and returns a function `g`.
887
     * When applied, `g` returns the result of applying `f` to the arguments provided initially followed by the arguments provided to `g`.
888
     *
889
     * Special placeholder value `P::__` may be used to specify "gaps", allowing partial application of any combination of arguments, regardless of their positions.
890
     *
891
     * @phlnSignature ((a, b, c, ..., n) -> x) -> [a, b, c, ...] -> ((d, e, f, ..., n) -> x)
892
     * @phlnCategory function
893
     * @param callable $fn
894
     * @param array $args
895
     * @return \Closure
896
     * @example
897
     *      $subtractFive = P::partial(P::subtract, [P::__, 5]);
898
     *      $subtractFive(10); // 5
899
     */
900
    public static function partial(callable $fn = NULL, array $args = []): \Closure
901
    {
902
        return \phln\fn\partial(...func_get_args());
903
    }
904
905
    /**
906
     * Takes a function `f` and a list of arguments, and returns a function `g`. When applied, `g` returns the result of applying `f` to the arguments provided initially followed by the arguments provided to `g`.
907
     *
908
     * @phlnSignature ((a, b, c, d, ..., n) -> x) -> [d, ..., n] -> ((a, b, c) -> x)
909
     * @phlnCategory function
910
     * @param callable $fn
911
     * @param array $args
912
     * @return \Closure
913
     * @example
914
     *      $hello = function ($salutations, $name, $lastname) {
915
     *          return "{$salutations}, {$name} {$lastname}";
916
     *      };
917
     *
918
     *      $f = P::partialRight($hello, ['Jon', 'Stark']);
919
     *      $f('Hello'); // 'Hello, Jon Stark'
920
     */
921
    public static function partialRight(callable $fn = NULL, array $args = NULL): \Closure
922
    {
923
        return \phln\fn\partialRight(...func_get_args());
924
    }
925
926
    /**
927
     * Performs left-to-right function composition.
928
     * The leftmost function may have any arity; the remaining functions must be unary.
929
     *
930
     * **Note**: The result of pipe is not automatically curried.
931
     *
932
     * @phlnSignature [((a, b, ..., n) -> o), (o -> p), ..., (x -> y), (y -> z)] -> (a, b, ..., n) -> z)
933
     * @phlnCategory function
934
     * @param callable[] $fns
935
     * @return \Closure
936
     * @throws \UnderflowException
937
     */
938
    public static function pipe(array $fns): \Closure
939
    {
940
        return \phln\fn\pipe(...func_get_args());
941
    }
942
943
    /**
944
     * Returns a new function much like the supplied one, except that the first two arguments' order is reversed.
945
     *
946
     * @phlnSignature (a -> b -> c -> ... -> z) -> (b -> a -> c -> ... -> z)
947
     * @phlnCategory function
948
     * @param callable $f
949
     * @return \Closure
950
     * @example
951
     *      $serialize = function ($a, $b) {
952
     *          return "a:{$a},b:{$b}";
953
     *      };
954
     *      P::swap($serialize)(2, 1); // 'a:1,b:2'
955
     */
956
    public static function swap(callable $f): \Closure
957
    {
958
        return \phln\fn\swap(...func_get_args());
959
    }
960
961
    /**
962
     * Runs the given function with the supplied object, then returns the object.
963
     *
964
     * @phlnSignature (a -> *) -> a -> a
965
     * @phlnCategory function
966
     * @param string|callable $fn
967
     * @param mixed $value
968
     * @return \Closure|mixed
969
     * @example
970
     *      $dump = P::tap('var_dump');
971
     *      $dump('foo'); // var_dumps('foo'); returns 'foo'
972
     */
973
    public static function tap(callable $fn = NULL, $value = NULL)
974
    {
975
        return \phln\fn\tap(...func_get_args());
976
    }
977
978
    /**
979
     * Returns callback which throws given exception.
980
     *
981
     * *Note:* exceptions are considered as side-efects. Use it with caution.
982
     *
983
     * @phlnSignature (String, [*]) -> (*... -> Null)
984
     * @phlnCategory function
985
     * @param string $exception
986
     * @param array $args
987
     * @return \Closure
988
     * @example
989
     *      $break = P::throwException(\LogicException::class);
990
     *      $break(); // -> throw new \LogicException()
991
     */
992
    public static function throwException(string $exception = 'Exception', array $args = []): \Closure
993
    {
994
        return \phln\fn\throwException(...func_get_args());
995
    }
996
997
    /**
998
     * Takes a function `fn`, which takes a single array argument, and returns a function which:
999
     * * takes any number of positional arguments;
1000
     * * passes these arguments to `fn` as an array and returns the result
1001
     *
1002
     * In other words, `P::unapply` derives a variadic function from a function which takes an array. `P::unapply` is the inverse of `P::apply`.
1003
     *
1004
     * @phlnSignature ([*...] -> a) -> (*... -> a)
1005
     * @phlnCategory function
1006
     * @param string|callable $fn
1007
     * @param array ...$args
1008
     * @return \Closure|mixed
1009
     * @example
1010
     *      P::unapply('\\json_encode')(1, 2, 3); // [1,2,3]
1011
     */
1012
    public static function unapply(callable $fn = NULL, ...$args)
1013
    {
1014
        return \phln\fn\unapply(...func_get_args());
1015
    }
1016
1017
    /**
1018
     * Takes a list of predicates and returns a predicate that returns `true` for a given list of arguments if every one of the provided predicates is satisfied by those arguments.
1019
     *
1020
     * The function returned is a curried function whose arity matches that of the highest-arity predicate.
1021
     *
1022
     * @phlnSignature [(*... -> Boolean) -> *... -> Boolean
1023
     * @phlnCategory logic
1024
     * @param array $predicates
1025
     * @return callable
1026
     * @example
1027
     *      $ace = P::propEq('rank', 'A');
1028
     *      $spades = P::propEq('suit', '♠︎');
1029
     *      $aceOfSpades = P::allPass([$ace, $spades]);
1030
     *      $aceOfSpades(['rank' => 'A', 'suit' => '♠︎']); // true
1031
     */
1032
    public static function allPass(array $predicates): callable
1033
    {
1034
        return \phln\logic\allPass(...func_get_args());
1035
    }
1036
1037
    /**
1038
     * Returns `true` when both of two provided values are truthy.
1039
     *
1040
     * This function is polymorphic and supports two cases:
1041
     * 1. when both values are predicates it will return wrapper function which call to the two functions in an `&&` operation, returning `true` if both of the functions will return truthy value.
1042
     * 2. when both values are booleans it will return result of `&&` operation
1043
     *
1044
     * @phlnSignature (*... -> Boolean) -> (*... -> Boolean) -> (*... -> Boolean)
1045
     * @phlnSignature Boolean -> Boolean -> Boolean
1046
     * @phlnCategory logic
1047
     * @param string|callable|bool $left
1048
     * @param string|callable|bool $right
1049
     * @return \Closure|bool
1050
     * @example
1051
     *      $gt10 = P::partial(P::gt, [P::__, 10]);
1052
     *      $lt20 = P::partial(P::lt, [P::__, 20]);
1053
     *      $f = P::both($gt10, $lt20);
1054
     *      $f(12); // true
1055
     *      P::both(true, false); // false
1056
     */
1057
    public static function both($left = NULL, $right = NULL)
1058
    {
1059
        return \phln\logic\both(...func_get_args());
1060
    }
1061
1062
    /**
1063
     * Returns a function, `fn`, which encapsulates `if/else`, `if/else`, ... logic. `P::cond` takes a list of [`predicate`, `transformer`] pairs. All of the arguments to `fn` are applied to each of the `predicates` in turn until one returns a truth-y value, at which point `fn` returns the result of applying its arguments to the corresponding `transformer`. If none of the `predicates` matches, `fn` returns null.
1064
     *
1065
     * @phlnSignature [[(*… → Boolean),(*… → *)]] → (*… → *)
1066
     * @phlnCategory logic
1067
     * @param array $pairs
1068
     * @return \Closure
1069
     * @example
1070
     *      $fn = P::cond([
1071
     *          [P::equals(0), P::always('water freezes at 0°C')],
1072
     *          [P::equals(100), P::always('water boils at 100°C')],
1073
     *          [P::T, function(temp) {
1074
     *              return 'nothing special happens at ' + temp + '°C';
1075
     *          }]
1076
     *      ]);
1077
     *
1078
     *      $fn(0); //=> 'water freezes at 0°C'
1079
     *      $fn(50); //=> 'nothing special happens at 50°C'
1080
     *      $fn(100); //=> 'water boils at 100°C'
1081
     */
1082
    public static function cond(array $pairs): \Closure
1083
    {
1084
        return \phln\logic\cond(...func_get_args());
1085
    }
1086
1087
    /**
1088
     * Returns the second argument if it is not `null`; otherwise the first argument is returned.
1089
     *
1090
     * @phlnSignature a -> b -> b | a
1091
     * @phlnCategory logic
1092
     * @param mixed $default
1093
     * @param mixed $value
1094
     * @return \Closure|mixed
1095
     * @example
1096
     *      P::defaultTo(42, null); // 42
1097
     *      P::defaultTo(42, 'life'); // 'life'
1098
     */
1099
    public static function defaultTo($default = NULL, $value = NULL)
1100
    {
1101
        return \phln\logic\defaultTo(...func_get_args());
1102
    }
1103
1104
    /**
1105
     * Returns `true` when one of two provided values is truthy.
1106
     *
1107
     * This function is polymorphic and supports two cases:
1108
     * 1. when both values are predicates it will return wrapper function which call to the two functions in an `||` operation, returning `true` if at least one of the functions will return truthy value.
1109
     * 2. when both values are booleans it will return result of `||` operation
1110
     *
1111
     * @phlnSignature (*... -> Boolean) -> (*... -> Boolean) -> (*... -> Boolean)
1112
     * @phlnSignature Boolean -> Boolean -> Boolean
1113
     * @phlnCategory logic
1114
     * @param string|callable|bool $left
1115
     * @param string|callable|bool $right
1116
     * @return \Closure|bool
1117
     * @example
1118
     *      $lt10 = P::partial(P::lt, [P::__, 10]);
1119
     *      $gt20 = P::partial(P::gt, [P::__, 20]);
1120
     *      $f = P::either($lt10, $gt20);
1121
     *      $f(12); // false
1122
     *      $f(9); // true
1123
     *      $f(21); // true
1124
     *      P::either(true, false); // true
1125
     */
1126
    public static function either($left = NULL, $right = NULL)
1127
    {
1128
        return \phln\logic\either(...func_get_args());
1129
    }
1130
1131
    /**
1132
     * Creates a function that will process either the `onTrue` or the `onFalse` function depending upon the result of the condition predicate.
1133
     *
1134
     * @phlnSignature (*... -> Boolean) -> (*... -> *) -> (*... -> *) -> (*... -> *)
1135
     * @phlnCategory logic
1136
     * @param callable $predicate
1137
     * @param callable $onTrue
1138
     * @param callable $onFalse
1139
     * @return \Closure
1140
     * @example
1141
     *      $modulo15 = P::swap(P::modulo)(15);
1142
     *      $fizzbuzz = P::ifElse(
1143
     *          P::compose(P::equals(0), $modulo15),
1144
     *          P::always('fizzbuzz'),
1145
     *          P::identity
1146
     *      );
1147
     *
1148
     *      $fizzbuzz(15); // 'fizzbuzz'
1149
     *      $fizzbuzz(1); // 1
1150
     */
1151
    public static function ifElse(callable $predicate = NULL, callable $onTrue = NULL, callable $onFalse = NULL): \Closure
1152
    {
1153
        return \phln\logic\ifElse(...func_get_args());
1154
    }
1155
1156
    /**
1157
     * Returns `true` if the given value is its type's empty value; `false` otherwise.
1158
     *
1159
     * *Note* unlike `\empty()` this function will consider numbers, booleans and NULL as non-empty.
1160
     *
1161
     * @phlnSignature a -> Boolean
1162
     * @phlnCategory logic
1163
     * @param $value
1164
     * @return bool
1165
     * @example
1166
     *      P::isEmpty(''); // true
1167
     *      P::isEmpty([]); // true
1168
     *      P::isEmpty(new stdClass); // true
1169
     *      P::isEmpty(0); // false
1170
     *      P::isEmpty(null); // false
1171
     *      P::isEmpty(false); // false
1172
     *      P::isEmpty(true); // false
1173
     */
1174
    public static function isEmpty($value): bool
1175
    {
1176
        return \phln\logic\isEmpty(...func_get_args());
1177
    }
1178
1179
    /**
1180
     * A function that returns the `!` of its argument. It will return `true` when passed false-y value, and `false` when passed a truth-y one.
1181
     *
1182
     * @phlnSignature * -> Boolean
1183
     * @phlnCategory logic
1184
     * @param $value
1185
     * @return bool
1186
     * @example
1187
     *      P::not(0); // true
1188
     *      P::not(true); // false
1189
     */
1190
    public static function not($value): bool
1191
    {
1192
        return \phln\logic\not(...func_get_args());
1193
    }
1194
1195
    /**
1196
     * Add two values
1197
     *
1198
     * @phlnSignature Number a => a -> a -> a
1199
     * @phlnCategory math
1200
     * @param mixed $a
1201
     * @param mixed $b
1202
     * @return \Closure|mixed
1203
     */
1204
    public static function add($a = NULL, $b = NULL)
1205
    {
1206
        return \phln\math\add(...func_get_args());
1207
    }
1208
1209
    /**
1210
     * Decrement its argument
1211
     *
1212
     * @phlnSignature Int a => a -> a
1213
     * @phlnCategory math
1214
     * @param mixed $number
1215
     * @return mixed
1216
     */
1217
    public static function dec($number)
1218
    {
1219
        return \phln\math\dec(...func_get_args());
1220
    }
1221
1222
    /**
1223
     * Divide numbers. Equivalent of `a / b`
1224
     *
1225
     * @phlnSignature Number a => a -> a -> a
1226
     * @phlnCategory math
1227
     * @param mixed $a
1228
     * @param mixed $b
1229
     * @return \Closure|mixed
1230
     */
1231
    public static function divide($a = NULL, $b = NULL)
1232
    {
1233
        return \phln\math\divide(...func_get_args());
1234
    }
1235
1236
    /**
1237
     * Increment its argument
1238
     *
1239
     * @phlnSignature Int a => a -> a
1240
     * @phlnCategory math
1241
     * @param mixed $number
1242
     * @return mixed
1243
     */
1244
    public static function inc($number)
1245
    {
1246
        return \phln\math\inc(...func_get_args());
1247
    }
1248
1249
    /**
1250
     * Returns the mean of the given list of numbers.
1251
     *
1252
     * @phlnSignature Number a => [a] -> a
1253
     * @phlnCategory math
1254
     * @param array $numbers
1255
     * @example
1256
     *      P::mean([2, 7, 9]) // 6
1257
     * @return \Closure|mixed
1258
     */
1259
    public static function mean(array $numbers)
1260
    {
1261
        return \phln\math\mean(...func_get_args());
1262
    }
1263
1264
    /**
1265
     * Returns the median of the given list of numbers.
1266
     *
1267
     * @phlnSignature Number a => [a] -> a
1268
     * @phlnCategory math
1269
     * @param string|array $numbers
1270
     * @return mixed
1271
     * @example
1272
     *      \\phln\\math\\median([7, 2, 9]) // 7
1273
     *      \\phln\\math\\median([7, 2, 10, 9]) // 8
1274
     */
1275
    public static function median(array $numbers)
1276
    {
1277
        return \phln\math\median(...func_get_args());
1278
    }
1279
1280
    /**
1281
     * Divides the first parameter by the second and returns the remainder.
1282
     *
1283
     * @phlnSignature Number a => a -> a -> a
1284
     * @phlnCategory math
1285
     * @param string $a
1286
     * @param string $b
1287
     * @return \Closure|mixed
1288
     * @example
1289
     *      \\phln\\math\\modulo(1, 2) // 1
1290
     */
1291
    public static function modulo($a = NULL, $b = NULL)
1292
    {
1293
        return \phln\math\modulo(...func_get_args());
1294
    }
1295
1296
    /**
1297
     * Multiplies two numbers
1298
     *
1299
     * @phlnSignature Number a => a -> a -> a
1300
     * @phlnCategory math
1301
     * @param string $a
1302
     * @param string $b
1303
     * @return \Closure|mixed
1304
     * @example
1305
     *      $triple = P::multiply(3);
1306
     *      $triple(7); // 21
1307
     */
1308
    public static function multiply($a = NULL, $b = NULL)
1309
    {
1310
        return \phln\math\multiply(...func_get_args());
1311
    }
1312
1313
    /**
1314
     * Multiplies together all the elements of a list.
1315
     *
1316
     * @phlnSignature Number a => [a] -> a
1317
     * @phlnCategory math
1318
     * @param array $numbers
1319
     * @return mixed
1320
     * @example
1321
     *      P::product([2, 4, 6, 8, 100, 1]); // 38400
1322
     */
1323
    public static function product(array $numbers)
1324
    {
1325
        return \phln\math\product(...func_get_args());
1326
    }
1327
1328
    /**
1329
     * Subtracts its second argument from its first argument.
1330
     *
1331
     * @phlnSignature Number a => a -> a -> a
1332
     * @phlnCategory math
1333
     * @param number $a
1334
     * @param number $b
1335
     * @return \Closure|mixed
1336
     * @example
1337
     *      $complementaryAngle = P::subtract(90);
1338
     *      $complementaryAngle(30); //=> 60
1339
     */
1340
    public static function subtract($a = NULL, $b = NULL)
1341
    {
1342
        return \phln\math\subtract(...func_get_args());
1343
    }
1344
1345
    /**
1346
     * Adds together all the elements of a list.
1347
     *
1348
     * @phlnSignature [Number] -> Number
1349
     * @phlnCategory math
1350
     * @param array $numbers
1351
     * @return mixed
1352
     * @example
1353
     *      P::sum([1, 2, 3, 4]); // 10
1354
     */
1355
    public static function sum(array $numbers)
1356
    {
1357
        return \phln\math\sum(...func_get_args());
1358
    }
1359
1360
    /**
1361
     * Reports whether two objects have the same value, in `P::equals` terms, for the specified property.
1362
     *
1363
     * @phlnSignature k -> {k: v} -> {k: v} -> Boolean
1364
     * @phlnCategory object
1365
     * @param string $prop
1366
     * @param array|object $a
1367
     * @param array|object $b
1368
     * @return \Closure|mixed
1369
     * @example
1370
     *      P::eqProps('name', ['name' => 'Jon'], ['name' => 'Jon']); // true
1371
     */
1372
    public static function eqProps(string $prop = '', $a = [], $b = [])
1373
    {
1374
        return \phln\object\eqProps(...func_get_args());
1375
    }
1376
1377
    /**
1378
     * Returns a list containing the names of array keys.
1379
     *
1380
     * @phlnSignature {k: v} -> [k]
1381
     * @phlnCategory object
1382
     * @param array|object $object
1383
     * @return array
1384
     * @see \array_keys()
1385
     * @see \get_object_vars()
1386
     * @example
1387
     *      P::keys(['a' => 1, 'b' => 1]); // ['a', 'b']
1388
     */
1389
    public static function keys($object): array
1390
    {
1391
        return \phln\object\keys(...func_get_args());
1392
    }
1393
1394
    /**
1395
     * Create a new object with the keys of the first object merged with the keys of the second object. If a key exists in both objects, the value from the second object will be used.
1396
     *
1397
     * @phlnSignature {k: v} -> {k: v} -> {k: v}
1398
     * @phlnCategory object
1399
     * @param array|object $left
1400
     * @param array|object $right
1401
     * @return \Closure|array
1402
     * @example
1403
     *      $toDefaults = P::partial(P::merge, [P::__, ['x' => 0]);
1404
     *      $toDefaults(['x' => 2, 'y' => 1]); // ['x' => 0, 'y' => 1]
1405
     */
1406
    public static function merge($left = [], $right = [])
1407
    {
1408
        return \phln\object\merge(...func_get_args());
1409
    }
1410
1411
    /**
1412
     * Creates an object containing a single key:value pair.
1413
     *
1414
     * @phlnSignature String -> a -> { String: a }
1415
     * @phlnCategory object
1416
     * @param string $key
1417
     * @param mixed $value
1418
     * @return \Closure|object
1419
     * @example
1420
     *      P::objOf('foo', 'bar'); // ['foo' => 'bar']
1421
     */
1422
    public static function objOf(string $key = NULL, $value = NULL)
1423
    {
1424
        return \phln\object\objOf(...func_get_args());
1425
    }
1426
1427
    /**
1428
     * Returns a partial copy of an object omitting the keys specified.
1429
     *
1430
     * @phlnSignature [String] -> {String: *} -> {String: *}
1431
     * @phlnCategory object
1432
     * @param array $omitKeys
1433
     * @param array|object $object
1434
     * @return \Closure|array
1435
     * @example
1436
     *      P::omit(['a', 'c'], ['a' => 1, 'b' => 2, 'c' => 3]); // ['b' => 2]
1437
     */
1438
    public static function omit(array $omitKeys = [], $object = [])
1439
    {
1440
        return \phln\object\omit(...func_get_args());
1441
    }
1442
1443
    /**
1444
     * Returns nested value using "dot notation".
1445
     *
1446
     * @phlnSignature String -> {k: v} -> v|Null
1447
     * @phlnCategory object
1448
     * @param string $path
1449
     * @param array|object $object
1450
     * @return \Closure|mixed
1451
     * @example
1452
     *      P::path('a.b', ['a' => ['b' => 'foo']]); // 'foo'
1453
     *      P::path('a.b.c', ['a' => ['b' => 'foo']]); // null
1454
     */
1455
    public static function path(string $path = '', $object = [])
1456
    {
1457
        return \phln\object\path(...func_get_args());
1458
    }
1459
1460
    /**
1461
     * Returns nested value using "dot notation". If key is not defined, or value is NULL default value will be returned.
1462
     *
1463
     * @phlnSignature String -> a -> {k: v} -> v | a
1464
     * @phlnCategory object
1465
     * @param string $path
1466
     * @param mixed $default
1467
     * @param array $object
1468
     * @return \Closure|mixed
1469
     * @example
1470
     *      P::pathOr('a.b', 'foo', ['a' => ['b' => 1]]); // 1
1471
     *      P::pathOr('a.b', 'foo', ['a' => ['b' => 0]]); // 0
1472
     *      P::pathOr('a.b', 'foo', ['a' => ['b' => null]]); // 'foo'
1473
     *      P::pathOr('a.b', 'foo', ['a' => 1]); // 'foo'
1474
     */
1475
    public static function pathOr(string $path = '', $default = NULL, array $object = [])
1476
    {
1477
        return \phln\object\pathOr(...func_get_args());
1478
    }
1479
1480
    /**
1481
     * Returns a partial copy of an object containing only the keys specified. If the key does not exist, the property is ignored.
1482
     *
1483
     * @phlnSignature [String] -> {String: *} -> {String: *}
1484
     * @phlnCategory object
1485
     * @param array $useKeys
1486
     * @param array|object $object
1487
     * @return \Closure|array
1488
     * @example
1489
     *      P::pick(['a'], ['a' => 1, 'b' => 2]); // ['a' => 1]
1490
     */
1491
    public static function pick(array $useKeys = [], $object = [])
1492
    {
1493
        return \phln\object\pick(...func_get_args());
1494
    }
1495
1496
    /**
1497
     * Returns a function that when supplied an array returns the indicated key of that key, if it exists.
1498
     *
1499
     * @phlnSignature k -> {k: v} -> v
1500
     * @phlnCategory object
1501
     * @param string|integer $key
1502
     * @param array|object $array
1503
     * @return \Closure|mixed
1504
     */
1505
    public static function prop($key = '', $object = [])
1506
    {
1507
        return \phln\object\prop(...func_get_args());
1508
    }
1509
1510
    /**
1511
     * Acts as multiple `prop`: array of keys in, array of values out. Preserves order.
1512
     *
1513
     * @phlnSignature [k] -> {k: v} -> [v]
1514
     * @phlnCategory object
1515
     * @param array $props
1516
     * @param array|object $object
1517
     * @return \Closure|array
1518
     * @example
1519
     *      $fullName = P::compose(P::join(' '), P::props(['firstName', 'lastName']));
1520
     *      $fullName(['lastName' => 'Snow', 'firstName' => 'Jon']); // 'Jon Snow'
1521
     */
1522
    public static function props(array $props = [], $object = [])
1523
    {
1524
        return \phln\object\props(...func_get_args());
1525
    }
1526
1527
    /**
1528
     * Converts an object into an array of key-value arrays.
1529
     *
1530
     * Note that order of output is not guaranteed.
1531
     *
1532
     * @phlnSignature String k => { k: v } -> [[k, v]]
1533
     * @phlnCategory object
1534
     * @param array|object $object
1535
     * @return array
1536
     * @example
1537
     *      P::toPairs(['foo' => 1, 'bar' => 2]); // [['foo', 1], ['bar', 2]]
1538
     */
1539
    public static function toPairs($object): array
1540
    {
1541
        return \phln\object\toPairs(...func_get_args());
1542
    }
1543
1544
    /**
1545
     * Returns values of supplied object
1546
     *
1547
     * @phlnSignature {k: v} -> [v]
1548
     * @phlnCategory object
1549
     * @param array|object $object
1550
     * @return array
1551
     */
1552
    public static function values($object): array
1553
    {
1554
        return \phln\object\values(...func_get_args());
1555
    }
1556
1557
    /**
1558
     * Takes a spec object and a test object; returns `true` if the test satisfies the spec. Each of the spec's properties must be a predicate function. Each predicate is applied to the value of the corresponding property of the test object. where returns `true` if all the predicates return true, false otherwise.
1559
     *
1560
     * `where` is well suited to declaratively expressing constraints for other functions such as `filter` and `find`.
1561
     *
1562
     * @phlnSignature {String: (* -> Boolean)} -> {String: *} -> Boolean
1563
     * @phlnCategory object
1564
     * @param array $predicates
1565
     * @param array|object $object
1566
     * @return \Closure|bool
1567
     * @example
1568
     *      $verifyJon = P::where([
1569
     *          'firstName' => P::equals('Jon'),
1570
     *          'lastName' => P::equals('Snow'),
1571
     *      ]);
1572
     *
1573
     *      $verifyJon(['firstName' => 'Jon', 'lastName' => 'Snow', 'house' => 'Stark']); // true
1574
     */
1575
    public static function where(array $predicates = [], $object = [])
1576
    {
1577
        return \phln\object\where(...func_get_args());
1578
    }
1579
1580
    /**
1581
     * Takes a spec object and a test object; returns `true` if the test satisfies the spec, false otherwise. An object satisfies the spec if, for each of the spec's properties, accessing that property of the object gives the same value (in `P::equals()` terms) as accessing that property of the spec.
1582
     *
1583
     * @phlnSignature {String: *} -> {String: *} -> Boolean
1584
     * @phlnCategory object
1585
     * @param array $predicates
1586
     * @param array|object $object
1587
     * @return \Closure|bool
1588
     * @example
1589
     *      $verifyJon = P::whereEq(['firstName' => 'Jon', 'lastName' => 'Snow']);
1590
     *      $verifyJon(['firstName' => 'Jon', 'lastName' => 'Snow']); // true
1591
     */
1592
    public static function whereEq(array $predicates = [], $object = [])
1593
    {
1594
        return \phln\object\whereEq(...func_get_args());
1595
    }
1596
1597
    /**
1598
     * Restricts a number to be within a range.
1599
     *
1600
     * @phlnSignature Number a => a -> a -> a -> a
1601
     * @phlnCategory relation
1602
     * @param mixed $min
1603
     * @param mixed $max
1604
     * @param mixed $value
1605
     * @return \Closure|mixed
1606
     * @example
1607
     *      P::clamp(-1, 1, -100); // -1
1608
     *      P::clamp(-1, 1, 100); // 1
1609
     *      P::clamp(-1, 1, 0); // 0
1610
     */
1611
    public static function clamp($min = NULL, $max = NULL, $value = NULL)
1612
    {
1613
        return \phln\relation\clamp(...func_get_args());
1614
    }
1615
1616
    /**
1617
     * Finds the set (i.e. no duplicates) of all elements in the first list not contained in the second list.
1618
     *
1619
     * @phlnSignature [*] -> [*] -> [*]
1620
     * @phlnCategory relation
1621
     * @param array $left
1622
     * @param array $right
1623
     * @return \Closure|array
1624
     * @example
1625
     *      P::difference([1, 2, 3, 4], [3, 4, 5, 6]); // [1, 2]
1626
     */
1627
    public static function difference(array $left = NULL, array $right = NULL)
1628
    {
1629
        return \phln\relation\difference(...func_get_args());
1630
    }
1631
1632
    /**
1633
     * Returns `true` if its arguments are equivalent, `false` otherwise.
1634
     *
1635
     * @phlnSignature a -> b -> Boolean
1636
     * @phlnCategory relation
1637
     * @param mixed $a
1638
     * @param mixed $b
1639
     * @return \Closure|bool
1640
     * @example
1641
     *      P::equals(1, 1); // true
1642
     *      P::equals(1, '1'); // false
1643
     *      P::equals(1, 2); // false
1644
     */
1645
    public static function equals($a = NULL, $b = NULL)
1646
    {
1647
        return \phln\relation\equals(...func_get_args());
1648
    }
1649
1650
    /**
1651
     * Returns `true` if the first argument is greater than the second; `false` otherwise.
1652
     *
1653
     * @phlnSignature Ord a => a -> a -> Boolean
1654
     * @phlnCategory relation
1655
     * @param mixed $a
1656
     * @param mixed $b
1657
     * @return \Closure|bool
1658
     * @example
1659
     *      P::gt(2, 1); // true
1660
     */
1661
    public static function gt($a = NULL, $b = NULL)
1662
    {
1663
        return \phln\relation\gt(...func_get_args());
1664
    }
1665
1666
    /**
1667
     * Returns `true` if the first argument is greater than or equal to the second; `false` otherwise.
1668
     *
1669
     * @phlnSignature Ord a => a -> a -> Boolean
1670
     * @phlnCategory relation
1671
     * @param string $a
1672
     * @param string $b
1673
     * @return \Closure|mixed
1674
     * @example
1675
     *      P::gte(2, 1); // true
1676
     *      P::gte(2, 2); // true
1677
     *      P::gte(2, 3); // false
1678
     */
1679
    public static function gte($a = NULL, $b = NULL)
1680
    {
1681
        return \phln\relation\gte(...func_get_args());
1682
    }
1683
1684
    /**
1685
     * Combines two lists into a set composed of those elements common to both lists.
1686
     *
1687
     * @phlnSignature [*] -> [*] -> [*]
1688
     * @phlnCategory relation
1689
     * @param array $left
1690
     * @param array $right
1691
     * @return \Closure|mixed
1692
     * @example
1693
     *      P::intersection([1, 2, 3, 4], [6, 4, 5]); // [4]
1694
     */
1695
    public static function intersection(array $left = [], array $right = [])
1696
    {
1697
        return \phln\relation\intersection(...func_get_args());
1698
    }
1699
1700
    /**
1701
     * Returns `true` if the first argument is less than the second; `false` otherwise.
1702
     *
1703
     * @phlnSignature Ord a => a -> a -> Boolean
1704
     * @phlnCategory relation
1705
     * @param mixed $left
1706
     * @param mixed $right
1707
     * @return \Closure|bool
1708
     * @example
1709
     *      P::lt(1, 2); // true
1710
     *      P::lt(3, 2); // false
1711
     *      P::lt(2, 2); // false
1712
     */
1713
    public static function lt($left = NULL, $right = NULL)
1714
    {
1715
        return \phln\relation\lt(...func_get_args());
1716
    }
1717
1718
    /**
1719
     * Returns `true` if the first argument is less than or equal to the second; `false` otherwise.
1720
     *
1721
     * @phlnSignature Ord a => a -> a -> Boolean
1722
     * @phlnCategory relation
1723
     * @param mixed $left
1724
     * @param mixed $right
1725
     * @return \Closure|mixed
1726
     * @example
1727
     *      P::lte(1, 2); // true
1728
     */
1729
    public static function lte($left = NULL, $right = NULL)
1730
    {
1731
        return \phln\relation\lte(...func_get_args());
1732
    }
1733
1734
    /**
1735
     * Returns the larger of its two arguments.
1736
     *
1737
     * @phlnSignature a -> a -> a
1738
     * @phlnCategory relation
1739
     * @param mixed $left
1740
     * @param mixed $right
1741
     * @return \Closure|mixed
1742
     */
1743
    public static function max($left = NULL, $right = NULL)
1744
    {
1745
        return \phln\relation\max(...func_get_args());
1746
    }
1747
1748
    /**
1749
     * Returns the smaller of its two arguments.
1750
     *
1751
     * @phlnSignature a -> a -> a
1752
     * @phlnCategory relation
1753
     * @param mixed $left
1754
     * @param mixed $right
1755
     * @return \Closure|mixed
1756
     * @example
1757
     *      P::min(1, -1); // -1
1758
     */
1759
    public static function min($left = NULL, $right = NULL)
1760
    {
1761
        return \phln\relation\min(...func_get_args());
1762
    }
1763
1764
    /**
1765
     * Determines whether a nested path on an object has a specific value, in `equals()` terms.
1766
     *
1767
     * @phlnSignature String -> a -> {a} -> Boolean
1768
     * @phlnCategory relation
1769
     * @param string $path
1770
     * @param mixed $value
1771
     * @param array $object
1772
     * @return \Closure|bool
1773
     * @example
1774
     *      P::pathEq('foo.bar', 1, ['foo' => ['bar' => 1]]); // true
1775
     */
1776
    public static function pathEq(string $path = '', $value = NULL, array $object = [])
1777
    {
1778
        return \phln\relation\pathEq(...func_get_args());
1779
    }
1780
1781
    /**
1782
     * Returns `true` if the specified object property is equal, in `equals()` terms, to the given value; `false` otherwise.
1783
     *
1784
     * @phlnSignature k -> a -> {k: a} -> Boolean
1785
     * @phlnCategory relation
1786
     * @param string $prop
1787
     * @param mixed $value
1788
     * @param mixed $object
1789
     * @return \Closure|mixed
1790
     * @example
1791
     *      P::propEq('name', 'Jon', ['name' => 'Jon']); // true
1792
     */
1793
    public static function propEq(string $prop = '', $value = NULL, $object = NULL)
1794
    {
1795
        return \phln\relation\propEq(...func_get_args());
1796
    }
1797
1798
    /**
1799
     * Tests a regular expression against a String. Returns found string, or `NULL`. When regular expression has 'global' modifier function will return array of found strings.
1800
     *
1801
     * @phlnSignature RegExp -> String -> String|Null
1802
     * @phlnSignature RegExp -> String -> [String]
1803
     * @phlnCategory string
1804
     * @param string|RegExp $regexp
1805
     * @param string $test
1806
     * @return \Closure|array|string
1807
     * @example
1808
     *      P::match('/([a-z](o))/i', 'Lorem ipsum dolor'); // 'Lo'
1809
     *      P::match('/([a-z](o))/ig', 'Lorem ipsum dolor'); // ['Lo', 'do', 'lo']
1810
     */
1811
    public static function match($regexp = NULL, string $test = '')
1812
    {
1813
        return \phln\string\match(...func_get_args());
1814
    }
1815
1816
    /**
1817
     * Converts given string to RegExp object
1818
     *
1819
     * @phlnSignature String -> RegExp
1820
     * @phlnCategory string
1821
     * @param string $regexp
1822
     * @return RegExp
1823
     * @example
1824
     *      P::regexp('/foo/ig'); // => new \phln\RegExp('/foo/', 'ig');
1825
     */
1826
    public static function regexp(string $regexp): \phln\RegExp
1827
    {
1828
        return \phln\string\regexp(...func_get_args());
1829
    }
1830
1831
    /**
1832
     * Replace a regex match in a string with a replacement.
1833
     *
1834
     * When regular expression has 'global' modifier all matching strings will be replaced.
1835
     * Otherwise only first matching string will be replaced.
1836
     *
1837
     * @phlnSignature RegExp -> String -> String -> String
1838
     * @phlnCategory string
1839
     * @param string|RegExp $regexp
1840
     * @param string $replacement
1841
     * @param string $text
1842
     * @return \Closure|string
1843
     * @example
1844
     *      P::replace('/foo/', 'bar', 'foo foo foo'); // 'bar foo foo'
1845
     *      P::replace('/foo/g', 'bar', 'foo foo foo'); // 'bar bar bar'
1846
     */
1847
    public static function replace($regexp = NULL, string $replacement = '', string $text = '')
1848
    {
1849
        return \phln\string\replace(...func_get_args());
1850
    }
1851
1852
    /**
1853
     * Splits a string into an array of strings based on the given regular expression or separator.
1854
     *
1855
     * It's possible to split string
1856
     *
1857
     * @phlnSignature String -> String -> [String]
1858
     * @phlnSignature RegExp -> String -> [String]
1859
     * @phlnCategory string
1860
     * @param string|RegExp $delimiter
1861
     * @param string $text
1862
     * @return \Closure|array
1863
     * @example
1864
     *      P::split('/', 'a/b'); // ['a', 'b']
1865
     */
1866
    public static function split($delimiter = NULL, string $text = '')
1867
    {
1868
        return \phln\string\split(...func_get_args());
1869
    }
1870
1871
    /**
1872
     * Determines whether a given string matches a given regular expression.
1873
     *
1874
     * @phlnSignature RegExp -> String -> Bool
1875
     * @phlnSignature String -> String -> Bool
1876
     * @phlnCategory string
1877
     * @param string|RegExp $regexp
1878
     * @param string $string
1879
     * @return \Closure|bool
1880
     * @example
1881
     *      P::test('/foo/', 'foobar'); // true
1882
     */
1883
    public static function test($regexp = NULL, string $string = NULL)
1884
    {
1885
        return \phln\string\test(...func_get_args());
1886
    }
1887
1888
    /**
1889
     * See if `value` is of given `type`.
1890
     *
1891
     * Internally this function uses `\gettype()` with few support of few aliases:
1892
     * * `bool` - alias for `boolean` type
1893
     * * `float` - alias for `double` type
1894
     * * `callable` - checks if $value is valid callback
1895
     * * `function` - same as `callable`
1896
     * * class FQN - will check if supplied object is instance of given class
1897
     *
1898
     * @phlnSignature String -> a -> Boolean
1899
     * @phlnCategory type
1900
     * @param string $type
1901
     * @param mixed $value
1902
     * @return \Closure|bool
1903
     * @example
1904
     *      P::is('bool', true); // true
1905
     *      P::is(\stdClass::class, new \stdClass); // true
1906
     *      P::is(float, 1.1); // true
1907
     */
1908
    public static function is(string $type = '', $value = NULL)
1909
    {
1910
        return \phln\type\is(...func_get_args());
1911
    }
1912
1913
    /**
1914
     * Returns a function, `fn`, which encapsulates `if/else`, `if/else`, ... logic. `P::typeCond` takes a list of [`type`, `transformer`] pairs. Type is converted to `predicate` matching type of variable (in terms of `P::is()`). All of the arguments to `fn` are applied to each of the `predicates` in turn until one returns a truth-y value, at which point `fn` returns the result of applying its arguments to the corresponding `transformer`. If none of the `predicates` matches, `fn` returns null.
1915
     *
1916
     * @phlnSignature [[String, (*... -> *)]] -> (*... -> *)
1917
     * @phlnCategory type
1918
     * @phlnSee P::cond
1919
     * @param array $pairs
1920
     * @return \Closure
1921
     * @example
1922
     *      $count = P::typeCond([
1923
     *          ['string', '\\mb_strlen'],
1924
     *          ['array', '\\count'],
1925
     *          [P::T, P::always(0)],
1926
     *      ]);
1927
     *      $count('foo'); // 3
1928
     *      $count(['f', 'o', 'o']); // 3
1929
     *      $count(new stdClass); // 0
1930
     */
1931
    public static function typeCond(array $pairs): \Closure
1932
    {
1933
        return \phln\type\typeCond(...func_get_args());
1934
    }
1935
1936
}
1937