This repository was archived by the owner on Feb 6, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFunctionalCollection.php
More file actions
145 lines (134 loc) · 3.99 KB
/
FunctionalCollection.php
File metadata and controls
145 lines (134 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?php
namespace TryPhp;
class FunctionalCollection
{
/**
* collection to entries
* @var array
*/
private $values;
public function __construct(array $values = [])
{
$this->values = $values;
}
/**
* Method to create a immutable collection based off provided parameters
* @param mixed $values
* @return FunctionalCollection
*/
public function of(...$values): FunctionalCollection
{
$instance = new self();
$instance->values = $values;
return $instance;
}
/**
* Method to iterate mutable over the entries in the collection values
* @param callable $func
* @return FunctionalCollection
*/
public function map(callable $func): FunctionalCollection
{
foreach ($this->values as &$entry) {
$entry = $func($entry);
}
return $this;
}
/**
* Method to iterate over the collection and create a immutable copy, and filter out
* values not matching precicate
* @param callable $predicate
* @return FunctionalCollection
*/
public function filter(callable $predicate): FunctionalCollection
{
$currentValueSet = $this->extract();
foreach ($currentValueSet as $key => &$entry) {
if (!$predicate($entry)) {
unset($currentValueSet[$key]);
}
}
return new self(array_values($currentValueSet));
}
/**
* Method to return an generator iterator based off provided values
* @return \Generator
*/
public function generator(): \Generator
{
foreach ($this->values as $entry) {
yield $entry;
}
}
/**
* Method to retrieve set values
* @return array
*/
public function extract(): array
{
return $this->values;
}
/**
* Method to create immutable copy which contains concatination of set values and return values
* of provided closure
* @param callable $func
* @return FunctionalCollection
*/
public function extend(callable $func): FunctionalCollection
{
return new self($func($this->values));
}
/**
* Method to combine to collections and return an immutable copy with a combination from both collections' values
* @param FunctionalCollection $collection
* @return FunctionalCollection
*/
public function concat(FunctionalCollection $collection): FunctionalCollection
{
return new self(array_merge($this->values, $collection->extract()));
}
/**
* Methot to iterate over the entries of a collection, apply a closure and reduce them. Creates a immutable copy.
* @param callable $func
* @return FunctionalCollection
*/
public function chain(callable $func): FunctionalCollection
{
return new self($this->reduce(function ($val) use ($func) {
return $func($val);
}));
}
/**
* Method to combine values of a collection. Only scalar possible.
* @param callable|null $func
* @return mixed
*/
public function reduce(callable $func = null)
{
$accumulator = null;
foreach ($this->values as &$entry) {
$return = $entry;
if ($func !== null) {
$return = $func($entry);
}
if (!is_scalar($return) && !is_array($return)) {
throw new \TypeError('Return value is not scalar, and can therefore not be combined.');
}
if (is_string($return)) {
$accumulator .= $return;
continue;
}
if (is_numeric($return)) {
$accumulator += $return;
continue;
}
if (is_array($return)) {
$accumulator = array_merge([], (array) $accumulator, $return);
}
if (is_bool($return)) {
$accumulator = $accumulator && $return;
}
}
return $accumulator;
}
}