Skip to content

Commit 8857fd5

Browse files
committed
doc rewording
1 parent 47b8dcc commit 8857fd5

File tree

1 file changed

+79
-46
lines changed

1 file changed

+79
-46
lines changed

readme.md

Lines changed: 79 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,72 @@
33
[![Test Suite](https://github.com/dakujem/toru/actions/workflows/php-test.yml/badge.svg)](https://github.com/dakujem/toru/actions/workflows/php-test.yml)
44
[![Coverage Status](https://coveralls.io/repos/github/dakujem/toru/badge.svg?branch=trunk)](https://coveralls.io/github/dakujem/toru?branch=trunk)
55

6-
Toru is a standalone tool for _iterable_ collections for simple day-to-day tasks and advanced optimizations.
6+
Toru is a standalone tool for _iterable_ collections,
7+
ready for simple day-to-day tasks and advanced optimizations.
78
Most of its functionality is based on native _generators_ for efficiency with large data sets.
89

910
>
1011
> 💿 `composer require dakujem/toru`
1112
>
13+
> 📒 [Changelog](changelog.md)
14+
>
1215
13-
The package name comes from Japanese word "toru" (取る), which may mean "to take", "to pick up" or even "to collect".
14-
15-
Toru provides a few common **iteration primitives** (e.g. `map`, `filter`, `tap`),
16-
**aggregates** (e.g. `reduce`, `search`, `count`)
17-
and utility functions (e.g. `chain`) implemented using generators.
18-
19-
Also implements **Lodash-style fluent call chaining** to simplify composition of various transformations on iterable collections.
20-
21-
The aim of Toru is to provide simple tools to work with the native `iterable` type*.
22-
Leveraging generators, Toru enables memory-efficient operations on large datasets.
16+
Toru provides a few common
17+
- **iteration primitives** (e.g. `map`, `filter`, `tap`),
18+
- **aggregates** (e.g. `reduce`, `search`, `count`)
19+
- and utility functions (e.g. `chain`, `valuesOnly`, `slice`, `limit`)
2320

24-
All callable parameters (_mapper_, _predicate_, _reducer_ and _effect_ functions)
25-
always **receive keys** along with values.
26-
This is a key advantage over native functions like `array_map`, `array_reduce`, `array_walk`, or `array_filter`.
21+
... implemented using **generators**.
2722

28-
Use Toru when:
23+
TL;DR:
2924

30-
- in need to perform operations on `iterable` without converting to arrays
31-
- in need to work with _keys_, as alternative to `array_map`, `array_filter` or `array_reduce`
32-
- unable to use `foreach`
33-
- working with large datasets
34-
- running out of memory when transforming large collections (using arrays)
35-
- wanting to compose collection transformations neatly in fluent call chain, Lodash-style
36-
- in need of lazy evaluation (on-demand, per-element)
25+
- transform elements of native `iterable` type* collections (iterators and arrays) _without_ converting to arrays
26+
- keys (indexes) provided for every mapper, filter, reducer or effect function
27+
- fluent call chaining enabled (Lodash-style)
28+
- lazy per-element evaluation of transformations
29+
- transform large data sets without increasing memory usage
30+
- better memory efficiency of generators compared to native array functions
31+
- slower than native array functions or direct transformations inside a `foreach` block
3732

3833
>
3934
> \* The `iterable` is a built-in compile time type alias for `array|Traversable` encompassing all arrays and iterators,
4035
> so it's not exactly a native type, technically speaking.
4136
>
4237
38+
**Fluent call chaining** enables neat transformation composition.
39+
```php
40+
_dash($collection)
41+
->filter(predicate: $filterFunction)
42+
->map(values: $mapperFunction)
43+
->chain($moreElements)
44+
->valuesOnly();
45+
```
46+
47+
Toru enables **memory-efficient operations** on large data sets,
48+
because it leverages generators, which work on per-element basis and do not allocate extra memory.
49+
```php
50+
// no extra memory wasted on creating a filtered array
51+
$filtered = Itera::filter(input: $hugeDataSet, predicate: $filterFunction);
52+
foreach($filtered as $key => $value){ /* ... */ }
53+
```
54+
55+
All callable parameters always **receive keys** along with values.
56+
This is a key advantage over native functions like `array_map`, `array_reduce`, `array_walk`, or `array_filter`.
57+
```php
58+
$addresses = [
59+
'john.doe@example.com' => 'John Doe',
60+
'jane.doe@example.com' => 'Jane Doe',
61+
];
62+
$recipients = Itera::map(
63+
$addresses,
64+
fn($recipientName, $recipientAddress) => new Recipient($recipientAddress, $recipientName),
65+
);
66+
Mailer::send($mail, $recipients);
67+
```
68+
69+
> 🥋
70+
> The package name comes from Japanese word "toru" (取る), which may mean "to take", "to pick up" or even "to collect".
71+
4372

4473
## Examples
4574

@@ -99,7 +128,7 @@ Most of the primitives described in API section below are implemented in **3 for
99128

100129
Example of _filtering_ and _mapping_ a collection, then _appending_ some more already processed elements.
101130

102-
Usage of the individual static methods example:
131+
Usage of the individual **static methods**:
103132
```php
104133
use Dakujem\Toru\Itera;
105134

@@ -109,7 +138,18 @@ $merged = Itera::chain($mapped, $moreElements);
109138
$processed = Itera::valuesOnly(input: $merged);
110139
```
111140

112-
Usage of the partially applied methods example:
141+
Usage of the `Dash` wrapper for fluent **call chaining**:
142+
```php
143+
use Dakujem\Toru\Dash;
144+
145+
$processed = Dash::collect($collection)
146+
->filter(predicate: $filterFunction)
147+
->apply(values: $mapperFunction)
148+
->chain($moreElements)
149+
->valuesOnly();
150+
```
151+
152+
Usage of the **partially applied methods**:
113153
```php
114154
use Dakujem\Toru\Pipeline;
115155
use Dakujem\Toru\IteraFn;
@@ -123,20 +163,10 @@ $processed = Pipeline::through(
123163
);
124164
```
125165

126-
Usage of the `Dash` fluent wrapper example:
127-
```php
128-
use Dakujem\Toru\Dash;
129-
130-
$processed = Dash::collect($collection)
131-
->filter(predicate: $filterFunction)
132-
->apply(values: $mapperFunction)
133-
->chain($moreElements)
134-
->valuesOnly();
135-
```
136-
137-
The `$processed` collection can now be iterated over. All the above operations are applied at this point.
166+
The `$processed` collection can now be iterated over.
167+
All the above operations are applied at this point only, on per-element basis.
138168
```php
139-
foreach($processed as $value){
169+
foreach ($processed as $value) {
140170
// The filtered and mapped values from $collection will appear here,
141171
// followed by the elements present in $moreElements.
142172
}
@@ -1006,19 +1036,21 @@ You might not need this library.
10061036
- `mpetrovich/dash` provides a full range of transformation functions, uses _arrays_ internally
10071037
- `lodash-php/lodash-php` imitates Lodash and provides a full range of utilities, uses _arrays_ internally
10081038
- `nikic/iter` implements a range of iteration primitives using _generators_, authored by a PHP core team member
1009-
- `illuminate/collections` should cover the needs of most Laravel developers, check the inner implementation for details
1010-
- in many cases, a `foreach` will do the same job
1039+
- `illuminate/collections` should cover the needs of most Laravel developers, but uses _arrays_ internally
1040+
- in many cases, a `foreach` will do the job
10111041

1012-
This library (`dakujem/toru`) does not provide a full range of ready-made transformation functions,
1013-
rather provides the most common ones and means to bring in and compose own transformations.
1042+
Toru library (`dakujem/toru`) does not provide a full range of ready-made transformation functions,
1043+
rather provides the most common ones and means to bring in and compose own transformations.
1044+
It works well with and along with the aforementioned and other such libraries.
10141045

1015-
It originally started as an alternative to `nikic/iter` for daily tasks, which to me has a somewhat cumbersome interface.
1046+
Toru originally started as an alternative to `nikic/iter` for daily tasks,
1047+
which to me has a somewhat cumbersome interface.
10161048
The `Itera` static _class_ tries to fix that
10171049
by using a single class import instead of multiple function imports
10181050
and by reordering the parameters so that the input collection is consistently the first one.
1019-
Still, composing multiple operations into one transformation is cumbersome, so the `IteraFn` factory was implemented to fix that.
1020-
It worked well, but was still verbose for mundane tasks.
1021-
To allow concise fluent/chained calls (like with Lodash), the `Dash` class was designed.
1051+
Still, composing multiple operations into one transformation felt cumbersome, so the `IteraFn` factory was implemented to fix that.
1052+
It worked well, but was still kind of verbose for mundane tasks.
1053+
To allow concise fluent/chained calls (like with Lodash), the `Dash` class was then designed.
10221054
With it, it's possible to compose transformations neatly.
10231055

10241056

@@ -1031,7 +1063,8 @@ That being said, good quality PRs will be accepted.
10311063
Possible additions may include:
10321064

10331065
- `combine` values and keys
1034-
- `zip` multiple iterables
1066+
- `zip` multiple iterables (python, haskell, etc.)
1067+
- `alternate` multiple iterables (load-balance elements, mix)
10351068

10361069

10371070
---

0 commit comments

Comments
 (0)