iter-fest 0.1.1-main.1dec735 → 0.1.1-main.2a21293
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -29
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -16,23 +16,6 @@ Iterables can contains infinite number of items, please use this package respons
|
|
|
16
16
|
npm install iter-fest
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
### `Array.prototype` ports
|
|
20
|
-
|
|
21
|
-
We ported majority of functions from `Array.prototype.*` to `iterable*`.
|
|
22
|
-
|
|
23
|
-
```ts
|
|
24
|
-
import { iterableIncludes, iterableReduce } from 'iter-fest'; // Via default exports.
|
|
25
|
-
import { iterableSome } from 'iter-fest/iterableSome'; // Via named exports.
|
|
26
|
-
|
|
27
|
-
const iterable: Iterable<number> = [1, 2, 3, 4, 5].values();
|
|
28
|
-
|
|
29
|
-
console.log(iterableIncludes(iterable, 3)); // Prints "true".
|
|
30
|
-
console.log(iterableReduce(iterable, (sum, value) => sum + value, 0)); // Prints "15".
|
|
31
|
-
console.log(iterableSome(iterable, value => value % 2)); // Prints "true".
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
List of ported functions: [`at`](https://tc39.es/ecma262/#sec-array.prototype.at), [`concat`](https://tc39.es/ecma262/#sec-array.prototype.concat), [`entries`](https://tc39.es/ecma262/#sec-array.prototype.entries), [`every`](https://tc39.es/ecma262/#sec-array.prototype.every), [`filter`](https://tc39.es/ecma262/#sec-array.prototype.filter), [`find`](https://tc39.es/ecma262/#sec-array.prototype.find), [`findIndex`](https://tc39.es/ecma262/#sec-array.prototype.findindex), [`findLast`](https://tc39.es/ecma262/#sec-array.prototype.findlast), [`findLastIndex`](https://tc39.es/ecma262/#sec-array.prototype.findlastindex), [`forEach`](https://tc39.es/ecma262/#sec-array.prototype.foreach), [`includes`](https://tc39.es/ecma262/#sec-array.prototype.includes), [`indexOf`](https://tc39.es/ecma262/#sec-array.prototype.indexof), [`join`](https://tc39.es/ecma262/#sec-array.prototype.join), [`keys`](https://tc39.es/ecma262/#sec-array.prototype.keys), [`map`](https://tc39.es/ecma262/#sec-array.prototype.map), [`reduce`](https://tc39.es/ecma262/#sec-array.prototype.reduce), [`slice`](https://tc39.es/ecma262/#sec-array.prototype.slice), [`some`](https://tc39.es/ecma262/#sec-array.prototype.some), [`toSpliced`](https://tc39.es/ecma262/#sec-array.prototype.tospliced), and [`toString`](https://tc39.es/ecma262/#sec-array.prototype.tostring).
|
|
35
|
-
|
|
36
19
|
## Conversions
|
|
37
20
|
|
|
38
21
|
| From | To | Function signature |
|
|
@@ -70,28 +53,31 @@ for (const value of iteratorToIterable(iterate())) {
|
|
|
70
53
|
}
|
|
71
54
|
```
|
|
72
55
|
|
|
73
|
-
Note: calling `[Symbol.iterator]` will not
|
|
56
|
+
Note: calling `[Symbol.iterator]()` or `[Symbol.asyncIterator]()` will not restart the iteration. This is because iterator is an instance of iteration and is not restartable.
|
|
74
57
|
|
|
75
58
|
### Converting an `Observable` to `AsyncIterableIterator`
|
|
76
59
|
|
|
77
|
-
`ReadableStream` can be used
|
|
60
|
+
`ReadableStream` can be used as an intermediate format when converting an `Observable` to `AsyncIterableIterator`.
|
|
78
61
|
|
|
79
62
|
Note: `Observable` is push-based and it does not support flow control. When converting to `AsyncIterableIteratorrr`, the internal buffer of `ReadableStream` could build up quickly.
|
|
80
63
|
|
|
81
64
|
```ts
|
|
82
65
|
const observable = Observable.from([1, 2, 3]);
|
|
83
66
|
const readable = observableSubscribeAsReadable(observable);
|
|
67
|
+
const iterable = readerValues(readable.getReader());
|
|
84
68
|
|
|
85
|
-
for await (const value of
|
|
69
|
+
for await (const value of iterable) {
|
|
86
70
|
console.log(value); // Prints "1", "2", "3".
|
|
87
71
|
}
|
|
88
72
|
```
|
|
89
73
|
|
|
74
|
+
Note: calling `[Symbol.asyncIterator]()` will not resubscribe and read from the start of the observable. This is because the intermediate format does not support restart.
|
|
75
|
+
|
|
90
76
|
### Converting an `AsyncIterable` to `Observable`
|
|
91
77
|
|
|
92
78
|
`Observable.from` converts `Iterable` into `Observable`. However, it does not convert `AsyncIterable`.
|
|
93
79
|
|
|
94
|
-
`observableFromAsync` will convert `AsyncIterable` into `Observable`.
|
|
80
|
+
`observableFromAsync` will convert `AsyncIterable` into `Observable`. It will try to restart the iteration by calling `[Symbol.asyncIterator]()`.
|
|
95
81
|
|
|
96
82
|
```ts
|
|
97
83
|
async function* generate() {
|
|
@@ -106,7 +92,9 @@ const next = value => console.log(value);
|
|
|
106
92
|
observable.subscribe({ next }); // Prints "1", "2", "3".
|
|
107
93
|
```
|
|
108
94
|
|
|
109
|
-
|
|
95
|
+
Note: `observableFromAsync` will call `[Symbol.asyncIterator]()` initially to restart the iteration where possible.
|
|
96
|
+
|
|
97
|
+
### Converting an `Observable` to `ReadableStream`
|
|
110
98
|
|
|
111
99
|
`ReadableStream` is powerful for transforming and piping stream of data. It can be formed using data from both push-based and pull-based source with backpressuree.
|
|
112
100
|
|
|
@@ -115,7 +103,6 @@ Note: `Observable` is push-based and it does not support flow control. When conv
|
|
|
115
103
|
```ts
|
|
116
104
|
const observable = Observable.from([1, 2, 3]);
|
|
117
105
|
const readable = observableSubscribeAsReadable(observable);
|
|
118
|
-
const reader = readable.getReader();
|
|
119
106
|
|
|
120
107
|
readable.pipeTo(stream.writable); // Will write 1, 2, 3.
|
|
121
108
|
```
|
|
@@ -136,12 +123,16 @@ const readableStream = new ReadableStream({
|
|
|
136
123
|
}
|
|
137
124
|
});
|
|
138
125
|
|
|
139
|
-
|
|
126
|
+
const iterable = readerValues(readableStream.getReader());
|
|
127
|
+
|
|
128
|
+
for await (const value of iterable) {
|
|
140
129
|
console.log(value); // Prints "1", "2", "3".
|
|
141
130
|
}
|
|
142
131
|
```
|
|
143
132
|
|
|
144
|
-
|
|
133
|
+
Note: `[Symbol.asyncIterator]()` will not restart the reader and read from start of the stream. Reader is not restartable and streams are not seekable.
|
|
134
|
+
|
|
135
|
+
### Converting an `AsyncIterable`/`Iterable` to `ReadableStream`
|
|
145
136
|
|
|
146
137
|
```ts
|
|
147
138
|
const iterable = [1, 2, 3].values();
|
|
@@ -150,6 +141,8 @@ const readable = iterableGetReadable(iterable);
|
|
|
150
141
|
readable.pipeTo(stream.writable); // Will write 1, 2, 3.
|
|
151
142
|
```
|
|
152
143
|
|
|
144
|
+
Note: `iterableGetReadable()` will call `[Symbol.iterator]()` initially to restart the iteration where possible.
|
|
145
|
+
|
|
153
146
|
## Others
|
|
154
147
|
|
|
155
148
|
### Typed `Observable`
|
|
@@ -158,9 +151,9 @@ readable.pipeTo(stream.writable); // Will write 1, 2, 3.
|
|
|
158
151
|
|
|
159
152
|
### Producer-consumer queue
|
|
160
153
|
|
|
161
|
-
`PushAsyncIterableIterator` is a simple push-based producer-consumer queue and designed to decouple the flow between a producer and consumer. The producer can push a new job at anytime. The consumer can pull a job at its own convenience.
|
|
154
|
+
`PushAsyncIterableIterator` is a simple push-based producer-consumer queue and designed to decouple the flow between a producer and consumer. The producer can push a new job at anytime. The consumer can pull a job at its own convenience via for-loop.
|
|
162
155
|
|
|
163
|
-
Compare to pull-based queue, a push-based queue is
|
|
156
|
+
Compare to pull-based queue, a push-based queue is very easy to use. However, pull-based queue offers better flow control as it will produce a job only if there is a consumer ready to consume.
|
|
164
157
|
|
|
165
158
|
For a full-featured producer-consumer queue that supports flow control, use `ReadableStream` instead.
|
|
166
159
|
|
|
@@ -223,6 +216,23 @@ const generator = generatorWithLastValue(
|
|
|
223
216
|
);
|
|
224
217
|
```
|
|
225
218
|
|
|
219
|
+
## `Array.prototype` ports
|
|
220
|
+
|
|
221
|
+
We ported majority of functions from `Array.prototype.*` to `iterable*`.
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import { iterableIncludes, iterableReduce } from 'iter-fest'; // Via default exports.
|
|
225
|
+
import { iterableSome } from 'iter-fest/iterableSome'; // Via named exports.
|
|
226
|
+
|
|
227
|
+
const iterable: Iterable<number> = [1, 2, 3, 4, 5].values();
|
|
228
|
+
|
|
229
|
+
console.log(iterableIncludes(iterable, 3)); // Prints "true".
|
|
230
|
+
console.log(iterableReduce(iterable, (sum, value) => sum + value, 0)); // Prints "15".
|
|
231
|
+
console.log(iterableSome(iterable, value => value % 2)); // Prints "true".
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
List of ported functions: [`at`](https://tc39.es/ecma262/#sec-array.prototype.at), [`concat`](https://tc39.es/ecma262/#sec-array.prototype.concat), [`entries`](https://tc39.es/ecma262/#sec-array.prototype.entries), [`every`](https://tc39.es/ecma262/#sec-array.prototype.every), [`filter`](https://tc39.es/ecma262/#sec-array.prototype.filter), [`find`](https://tc39.es/ecma262/#sec-array.prototype.find), [`findIndex`](https://tc39.es/ecma262/#sec-array.prototype.findindex), [`findLast`](https://tc39.es/ecma262/#sec-array.prototype.findlast), [`findLastIndex`](https://tc39.es/ecma262/#sec-array.prototype.findlastindex), [`forEach`](https://tc39.es/ecma262/#sec-array.prototype.foreach), [`includes`](https://tc39.es/ecma262/#sec-array.prototype.includes), [`indexOf`](https://tc39.es/ecma262/#sec-array.prototype.indexof), [`join`](https://tc39.es/ecma262/#sec-array.prototype.join), [`keys`](https://tc39.es/ecma262/#sec-array.prototype.keys), [`map`](https://tc39.es/ecma262/#sec-array.prototype.map), [`reduce`](https://tc39.es/ecma262/#sec-array.prototype.reduce), [`slice`](https://tc39.es/ecma262/#sec-array.prototype.slice), [`some`](https://tc39.es/ecma262/#sec-array.prototype.some), [`toSpliced`](https://tc39.es/ecma262/#sec-array.prototype.tospliced), and [`toString`](https://tc39.es/ecma262/#sec-array.prototype.tostring).
|
|
235
|
+
|
|
226
236
|
## Behaviors
|
|
227
237
|
|
|
228
238
|
### How this compares to the TC39 proposals?
|
|
@@ -271,18 +281,21 @@ Generator has more functionalities than iterator and array. It is not recommende
|
|
|
271
281
|
- Generator can define the return value
|
|
272
282
|
- `return { done: true, value: 'the very last value' }`
|
|
273
283
|
- Iterating generator using for-loop will not get any values from `{ done: true }`
|
|
284
|
+
- The `generatorWithLastValue()` will help capturing and retrieving the last return value
|
|
274
285
|
- Generator can receive feedback values from its iterator
|
|
275
286
|
- `generator.next('something')`, the feedback can be assigned to variable via `const feedback = yield;`
|
|
276
287
|
- For-loop cannot send feedbacks to generator
|
|
277
288
|
|
|
278
289
|
### When should I use `Iterable`, `IterableIterator` and `Iterator`?
|
|
279
290
|
|
|
280
|
-
For best compatibility, you should generally follow this API signature: use `Iterable` for inputs, and use `IterableIterator` for outputs. You should avoid exporting pure `Iterator`.
|
|
291
|
+
For best compatibility, you should generally follow this API signature: use `Iterable` for inputs, and use `IterableIterator` for outputs. You should avoid exporting pure `Iterator`. Sample function signature should looks below.
|
|
281
292
|
|
|
282
293
|
```ts
|
|
283
|
-
function
|
|
294
|
+
function myFunction<T>(input: Iterable<T>): IterableIterator<T>;
|
|
284
295
|
```
|
|
285
296
|
|
|
297
|
+
`IterableIterator` may opt to support restarting the iteration through `[Symbol.iterator]()`. When consuming an `IterableIterator`, you should call `[Symbol.iterator]()` to obtain a fresh iteration or use for-loop statement if possible. However, `[Symbol.iterator]()` is an opt-in feature and does not always guarantee a fresh iteration.
|
|
298
|
+
|
|
286
299
|
### What is on the roadmap?
|
|
287
300
|
|
|
288
301
|
We are planning to bring iterables and its siblings together, including:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iter-fest",
|
|
3
|
-
"version": "0.1.1-main.
|
|
3
|
+
"version": "0.1.1-main.2a21293",
|
|
4
4
|
"description": "A collection of utilities for iterations.",
|
|
5
5
|
"files": [
|
|
6
6
|
"./dist/"
|
|
@@ -378,6 +378,6 @@
|
|
|
378
378
|
"typescript": "^5.4.5"
|
|
379
379
|
},
|
|
380
380
|
"dependencies": {
|
|
381
|
-
"iter-fest": "^0.1.1-main.
|
|
381
|
+
"iter-fest": "^0.1.1-main.2a21293"
|
|
382
382
|
}
|
|
383
383
|
}
|