Skip to content

Commit 7ab5f0f

Browse files
authored
Release/2.0.0 (#41)
* feat: Add eager and lazy evaluation strategies with pipeline architecture.
1 parent 1ae8141 commit 7ab5f0f

79 files changed

Lines changed: 3754 additions & 3885 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 105 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ use TinyBlocks\Collection\Order;
6767
use TinyBlocks\Mapper\KeyPreservation;
6868

6969
$collection = Collection::createFrom(elements: [1, 2, 3, 4, 5])
70-
->add(elements: [6, 7])
70+
->add(6, 7)
7171
->filter(predicates: static fn(int $value): bool => $value > 3)
7272
->sort(order: Order::ASCENDING_VALUE)
7373
->map(transformations: static fn(int $value): int => $value * 2)
@@ -76,6 +76,31 @@ $collection = Collection::createFrom(elements: [1, 2, 3, 4, 5])
7676
# Output: [8, 10, 12, 14]
7777
```
7878

79+
### Extending Collection
80+
81+
Domain collections should extend the `Collection` class to inherit all collection behavior:
82+
83+
```php
84+
<?php
85+
86+
declare(strict_types=1);
87+
88+
namespace Example;
89+
90+
use TinyBlocks\Collection\Collection;
91+
92+
final class Invoices extends Collection
93+
{
94+
public function totalAmount(): float
95+
{
96+
return $this->reduce(
97+
accumulator: static fn(float $carry, Invoice $invoice): float => $carry + $invoice->amount,
98+
initial: 0.0
99+
);
100+
}
101+
}
102+
```
103+
79104
<div id='writing'></div>
80105

81106
### Writing
@@ -84,10 +109,10 @@ These methods enable adding, removing, and modifying elements in the Collection.
84109

85110
#### Adding elements
86111

87-
- `add`: Adds one or more elements to the Collection.
112+
- `add`: Returns a new collection with the specified elements appended.
88113

89114
```php
90-
$collection->add(elements: [1, 2, 3]);
115+
$collection->add(1, 2, 3);
91116
```
92117

93118
```php
@@ -96,53 +121,52 @@ These methods enable adding, removing, and modifying elements in the Collection.
96121

97122
#### Merging collections
98123

99-
- `merge`: Merges the elements of another Collectible into the current Collection lazily, without materializing either
100-
collection.
124+
- `merge`: Merges the elements of another Collectible into the current Collection.
101125

102126
```php
103127
$collectionA->merge(other: $collectionB);
104128
```
105129

106130
#### Removing elements
107131

108-
- `remove`: Removes a specific element from the Collection.
132+
- `remove`: Returns a new collection with all occurrences of the specified element removed.
109133

110134
```php
111135
$collection->remove(element: 1);
112136
```
113137

114-
- `removeAll`: Removes elements from the Collection.
138+
- `removeAll`: Returns a new collection with elements removed.
115139
</br></br>
116-
- **With a filter**: Removes only the elements that match the provided filter.
140+
- **With a predicate**: Removes only the elements that satisfy the given predicate.
117141

118142
```php
119-
$collection->removeAll(filter: static fn(Amount $amount): bool => $amount->value > 10.0);
143+
$collection->removeAll(predicate: static fn(Amount $amount): bool => $amount->value > 10.0);
120144
```
121145

122-
- **Without a filter**: Removes all elements from the Collection.
146+
- **Without a predicate**: Removes all elements from the Collection.
123147

124148
```php
125149
$collection->removeAll();
126150
```
127151

128-
<div id='ordering'></div>
152+
<div id='filtering'></div>
129153

130154
### Filtering
131155

132156
These methods enable filtering elements in the Collection based on specific conditions.
133157

134158
#### Filter by predicate
135159

136-
- `filter`: Filters elements in the Collection.
160+
- `filter`: Retains only elements satisfying all given predicates.
137161
</br></br>
138162

139-
- **With predicates**: Filter elements are based on the provided predicates.
163+
- **With predicates**: Retains elements that satisfy the provided predicates.
140164

141165
```php
142166
$collection->filter(predicates: static fn(Amount $amount): bool => $amount->value > 100);
143167
```
144168

145-
- **Without predicates**: Removes all empty or false values (e.g., `null`, `false`, empty arrays).
169+
- **Without predicates**: Removes all falsy values (e.g., `null`, `false`, `0`, `''`, empty arrays).
146170

147171
```php
148172
$collection->filter();
@@ -152,11 +176,11 @@ These methods enable filtering elements in the Collection based on specific cond
152176

153177
### Ordering
154178

155-
These methods enable sorting elements in the Collection based on the specified order and optional predicates.
179+
These methods enable sorting elements in the Collection based on the specified order and optional comparator.
156180

157-
#### Sort by order and custom predicate
181+
#### Sort by order and custom comparator
158182

159-
- `sort`: Sorts the Collection.
183+
- `sort`: Returns a new sorted collection.
160184

161185
```
162186
Order::ASCENDING_KEY: Sorts the collection in ascending order by key.
@@ -173,13 +197,15 @@ These methods enable sorting elements in the Collection based on the specified o
173197
$collection->sort(order: Order::DESCENDING_VALUE);
174198
```
175199

176-
Sort the Collection using a custom predicate to determine how elements should be
177-
compared.
200+
Sort the Collection using a custom comparator to determine how elements should be compared.
178201

179202
```php
180203
use TinyBlocks\Collection\Order;
181204

182-
$collection->sort(order: Order::ASCENDING_VALUE, predicate: static fn(Amount $amount): float => $amount->value);
205+
$collection->sort(
206+
order: Order::ASCENDING_VALUE,
207+
comparator: static fn(Amount $first, Amount $second): int => $first->value <=> $second->value
208+
);
183209
```
184210

185211
<div id='retrieving'></div>
@@ -197,62 +223,71 @@ elements, or finding elements that match a specific condition.
197223
$collection->count();
198224
```
199225

226+
#### Check if empty
227+
228+
- `isEmpty`: Determines whether the collection has no elements.
229+
230+
```php
231+
$collection->isEmpty();
232+
```
233+
200234
#### Retrieve by condition
201235

202-
- `findBy`: Finds the first element that matches one or more predicates.
236+
- `findBy`: Finds the first element that satisfies any given predicate, or returns `null` if no predicate matches.
237+
When called without predicates, it returns `null`.
203238

204239
```php
205240
$collection->findBy(predicates: static fn(CryptoCurrency $crypto): bool => $crypto->symbol === 'ETH');
206241
```
207242

208-
<div id='comparing'></div>
209-
210243
#### Retrieve single elements
211244

212245
- `first`: Retrieves the first element from the Collection or returns a default value if the Collection is empty.
213246

214247
```php
215-
$collection->first(defaultValueIfNotFound: 'default');
248+
$collection->first(defaultValueIfNotFound: 'fallback');
216249
```
217250

218-
- `getBy`: Retrieves an element by its index or returns a default value if the index is out of range.
251+
- `getBy`: Retrieves an element by its zero-based index or returns a default value if the index is out of bounds.
219252

220253
```php
221-
$collection->getBy(index: 0, defaultValueIfNotFound: 'default');
254+
$collection->getBy(index: 0, defaultValueIfNotFound: 'fallback');
222255
```
223256

224257
- `last`: Retrieves the last element from the Collection or returns a default value if the Collection is empty.
225258

226259
```php
227-
$collection->last(defaultValueIfNotFound: 'default');
260+
$collection->last(defaultValueIfNotFound: 'fallback');
228261
```
229262

230-
#### Retrieve collection elements
263+
#### Retrieve collection segments
231264

232-
- `slice`: Extracts a portion of the collection, starting at the specified index and retrieving the specified number of
233-
elements.
234-
If length is negative, it excludes many elements from the end of the collection.
235-
If length is not provided or set to -1, it returns all elements from the specified index to the end of the collection.
265+
- `slice`: Extracts a contiguous segment of the collection, starting at the specified offset.
266+
If length is negative, it excludes that many elements from the end.
267+
If length is not provided or set to -1, it returns all elements from the specified offset to the end.
236268

237269
```php
238-
$collection->slice(index: 1, length: 2);
270+
$collection->slice(offset: 1, length: 2);
239271
```
240272

273+
<div id='comparing'></div>
274+
241275
### Comparing
242276

243-
These methods enable comparing collections to check for equality or to apply other comparison logic.
277+
These methods enable comparing collections to check for equality or to verify element membership.
244278

245279
#### Check if collection contains element
246280

247-
- `contains`: Checks if the Collection contains a specific element.
281+
- `contains`: Checks if the Collection contains a specific element. Uses strict equality for scalars and loose equality
282+
for objects.
248283

249284
```php
250285
$collection->contains(element: 5);
251286
```
252287

253288
#### Compare collections for equality
254289

255-
- `equals`: Compares the current Collection with another collection to check if they are equal.
290+
- `equals`: Compares the current Collection with another collection for element-wise equality.
256291

257292
```php
258293
$collectionA->equals(other: $collectionB);
@@ -265,12 +300,20 @@ These methods enable comparing collections to check for equality or to apply oth
265300
These methods perform operations that return a single value based on the Collection's content, such as summing or
266301
combining elements.
267302

268-
- `reduce`: Combines all elements in the Collection into a single value using the provided aggregator function and an
269-
initial value.
270-
This method is helpful for accumulating results, like summing or concatenating values.
303+
- `reduce`: Combines all elements in the Collection into a single value using the provided accumulator function and an
304+
initial value. This method is helpful for accumulating results, like summing or concatenating values.
271305

272306
```php
273-
$collection->reduce(aggregator: static fn(float $carry, float $amount): float => $carry + $amount, initial: 0.0)
307+
$collection->reduce(
308+
accumulator: static fn(float $carry, float $amount): float => $carry + $amount,
309+
initial: 0.0
310+
);
311+
```
312+
313+
- `joinToString`: Joins all elements into a string with the given separator.
314+
315+
```php
316+
$collection->joinToString(separator: ', ');
274317
```
275318

276319
<div id='transforming'></div>
@@ -282,18 +325,18 @@ These methods allow the Collection's elements to be transformed or converted int
282325
#### Applying actions without modifying elements
283326

284327
- `each`: Executes actions on each element in the Collection without modification.
285-
The method is helpful for performing side effects, such as logging or adding elements to another collection.
328+
The method is helpful for performing side effects, such as logging or accumulating values.
286329

287330
```php
288-
$collection->each(actions: static fn(Invoice $invoice): void => $collectionB->add(elements: new InvoiceSummary(amount: $invoice->amount, customer: $invoice->customer)));
331+
$collection->each(actions: static fn(Amount $amount): void => $total += $amount->value);
289332
```
290333

291334
#### Grouping elements
292335

293-
- `groupBy`: Groups the elements in the Collection based on the provided grouping criterion.
336+
- `groupBy`: Groups the elements in the Collection based on the provided classifier.
294337

295338
```php
296-
$collection->groupBy(grouping: static fn(Amount $amount): string => $amount->currency->name);
339+
$collection->groupBy(classifier: static fn(Amount $amount): string => $amount->currency->name);
297340
```
298341

299342
#### Mapping elements
@@ -307,11 +350,7 @@ These methods allow the Collection's elements to be transformed or converted int
307350

308351
#### Flattening elements
309352

310-
- `flatten`: Flattens a collection by removing any nested collections and returning a single collection with all
311-
elements in a single level.
312-
313-
This method recursively flattens any iterable elements, combining them into one collection, regardless of their
314-
nesting depth.
353+
- `flatten`: Flattens nested iterables by exactly one level. Non-iterable elements are yielded as-is.
315354

316355
```php
317356
$collection->flatten();
@@ -322,33 +361,33 @@ These methods allow the Collection's elements to be transformed or converted int
322361
- `toArray`: Converts the Collection into an array.
323362

324363
```
325-
PreserveKeys::DISCARD: Converts while discarding the keys.
326-
PreserveKeys::PRESERVE: Converts while preserving the original keys.
364+
KeyPreservation::DISCARD: Converts while discarding the keys.
365+
KeyPreservation::PRESERVE: Converts while preserving the original keys.
327366
```
328367

329-
By default, `PreserveKeys::PRESERVE` is used.
368+
By default, `KeyPreservation::PRESERVE` is used.
330369

331370
```php
332371
use TinyBlocks\Mapper\KeyPreservation;
333372

334-
$collection->toArray(preserveKeys: KeyPreservation::DISCARD);
373+
$collection->toArray(keyPreservation: KeyPreservation::DISCARD);
335374
```
336375

337376
#### Convert to JSON
338377

339378
- `toJson`: Converts the Collection into a JSON string.
340379

341380
```
342-
PreserveKeys::DISCARD: Converts while discarding the keys.
343-
PreserveKeys::PRESERVE: Converts while preserving the original keys.
381+
KeyPreservation::DISCARD: Converts while discarding the keys.
382+
KeyPreservation::PRESERVE: Converts while preserving the original keys.
344383
```
345384

346-
By default, `PreserveKeys::PRESERVE` is used.
385+
By default, `KeyPreservation::PRESERVE` is used.
347386

348387
```php
349388
use TinyBlocks\Mapper\KeyPreservation;
350389

351-
$collection->toJson(preserveKeys: KeyPreservation::DISCARD);
390+
$collection->toJson(keyPreservation: KeyPreservation::DISCARD);
352391
```
353392

354393
<div id='faq'></div>
@@ -376,6 +415,15 @@ chained operations.
376415
However, this also means that some operations will consume the generator, and you cannot access the elements unless you
377416
recreate the `Collection`.
378417

418+
### 03. What is the difference between eager and lazy evaluation?
419+
420+
- **Eager evaluation** (`createFrom` / `createFromEmpty`): Elements are materialized immediately into an array, enabling
421+
constant-time access by index, count, and repeated iteration.
422+
423+
- **Lazy evaluation** (`createLazyFrom` / `createLazyFromEmpty`): Elements are processed on-demand through generators,
424+
consuming memory only as each element is yielded. Ideal for large datasets or pipelines where not all elements need to
425+
be materialized.
426+
379427
<div id='license'></div>
380428

381429
## License

phpstan.neon.dist

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ parameters:
44
level: 9
55
tmpDir: report/phpstan
66
ignoreErrors:
7-
- '#Unsafe usage of new static#'
8-
- '#does not specify its types#'
9-
- '#type specified in iterable type#'
10-
- '#Generator expects key type#'
7+
- '#mixed given#'
8+
- '#iterable type#'
9+
- '#of new static#'
10+
- '#generic interface#'
11+
- '#destructuring on mixed#'
1112
reportUnmatchedIgnoredErrors: false

0 commit comments

Comments
 (0)