Skip to content

Commit 17a5d5f

Browse files
authored
Add iterator and asyncIterator forEach helpers (#175)
* add iterator and asyncIterator forEach helpers * changelog + fix docstrings * fix docstring errors
1 parent e9863e5 commit 17a5d5f

13 files changed

+249
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- Remove internal xxxU helper functions that are not needed anymore in uncurried mode. https://github.com/rescript-association/rescript-core/pull/191
99
- Rename `Object.empty` to `Object.make` for consistency.
1010
- Add dynamic `import`. https://github.com/rescript-association/rescript-core/pull/178
11+
- Add `Iterator.forEach` and `AsyncIterator.forEach` helpers for iterators. https://github.com/rescript-association/rescript-core/pull/175
1112

1213
## 1.0.0
1314

src/Core__AsyncIterator.mjs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,16 @@
11
// Generated by ReScript, PLEASE EDIT WITH CARE
2-
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
2+
3+
4+
async function forEach(iterator, f) {
5+
var iteratorDone = false;
6+
while(!iteratorDone) {
7+
var match = await iterator.next();
8+
f(match.value);
9+
iteratorDone = match.done;
10+
};
11+
}
12+
13+
export {
14+
forEach ,
15+
}
16+
/* No side effect */

src/Core__AsyncIterator.res

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,13 @@ type value<'a> = {
66
}
77

88
@send external next: t<'a> => promise<value<'a>> = "next"
9+
10+
let forEach = async (iterator, f) => {
11+
let iteratorDone = ref(false)
12+
13+
while !iteratorDone.contents {
14+
let {done, value} = await iterator->next
15+
f(value)
16+
iteratorDone := done
17+
}
18+
}

src/Core__AsyncIterator.resi

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,23 @@ let processMyAsyncIterator = async () => {
5858
*/
5959
@send
6060
external next: t<'a> => promise<value<'a>> = "next"
61+
62+
/**
63+
`forEach(iterator, fn)` consumes all values in the async iterator and runs the callback `fn` for each value.
64+
65+
See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) on MDN.
66+
67+
## Examples
68+
```rescript
69+
// Let's pretend we get an async iterator returning ints from somewhere.
70+
@val external asyncIterator: AsyncIterator.t<int> = "someAsyncIterator"
71+
72+
await asyncIterator->AsyncIterator.forEach(value =>
73+
switch value {
74+
| Some(value) if value > 10 => Console.log("More than 10!")
75+
| _ => ()
76+
}
77+
)
78+
```
79+
*/
80+
let forEach: (t<'a>, option<'a> => unit) => promise<unit>

src/Core__Iterator.mjs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,16 @@
11
// Generated by ReScript, PLEASE EDIT WITH CARE
2-
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
2+
3+
4+
function forEach(iterator, f) {
5+
var iteratorDone = false;
6+
while(!iteratorDone) {
7+
var match = iterator.next();
8+
f(match.value);
9+
iteratorDone = match.done;
10+
};
11+
}
12+
13+
export {
14+
forEach ,
15+
}
16+
/* No side effect */

src/Core__Iterator.res

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,13 @@ type value<'a> = {
88
@send external next: t<'a> => value<'a> = "next"
99
external toArray: t<'a> => array<'a> = "Array.from"
1010
external toArrayWithMapper: (t<'a>, 'a => 'b) => array<'b> = "Array.from"
11+
12+
let forEach = (iterator, f) => {
13+
let iteratorDone = ref(false)
14+
15+
while !iteratorDone.contents {
16+
let {done, value} = iterator->next
17+
f(value)
18+
iteratorDone := done
19+
}
20+
}

src/Core__Iterator.resi

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript
3131
## Examples
3232
```rescript
3333
@val external someIterator: Iterator.t<int> = "someIterator"
34+
3435
// Pulls out the next value of the iterator
3536
let {Iterator.done, value} = someIterator->Iterator.next
3637
```
@@ -79,3 +80,22 @@ Console.log(mapKeysAsArray) // Logs [7, 8] to the console.
7980
```
8081
*/
8182
external toArrayWithMapper: (t<'a>, 'a => 'b) => array<'b> = "Array.from"
83+
84+
/**
85+
`forEach(iterator, fn)` consumes all values in the iterator and runs the callback `fn` for each value.
86+
87+
See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) on MDN.
88+
89+
## Examples
90+
```rescript
91+
@val external someIterator: Iterator.t<int> = "someIterator"
92+
93+
someIterator->Iterator.forEach(value =>
94+
switch value {
95+
| Some(value) if value > 10 => Console.log("More than 10!")
96+
| _ => ()
97+
}
98+
)
99+
```
100+
*/
101+
let forEach: (t<'a>, option<'a> => unit) => unit

src/Core__List.resi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,9 @@ with `f`. Returns an empty list if `length` is negative.
185185
## Examples
186186
187187
```rescript
188-
List.fromInitializer(5, i => i) // list{0, 1, 2, 3, 4}
188+
List.fromInitializer(~length=5, i => i) // list{0, 1, 2, 3, 4}
189189
190-
List.fromInitializer(5, i => i * i) // list{0, 1, 4, 9, 16}
190+
List.fromInitializer(~length=5, i => i * i) // list{0, 1, 4, 9, 16}
191191
```
192192
*/
193193
let fromInitializer: (~length: int, int => 'a) => t<'a>

src/RescriptCore.res

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,36 @@ value.
5959
6060
## Examples
6161
62-
`MathUtils.res` file:
62+
`Core__Array.res` file:
6363
6464
```rescript
65-
let add = (a, b) => a + b
66-
let sub = (a, b) => a - b
65+
@send external indexOf: (array<'a>, 'a) => int = "indexOf"
66+
67+
let indexOfOpt = (arr, item) =>
68+
switch arr->indexOf(item) {
69+
| -1 => None
70+
| index => Some(index)
71+
}
6772
```
68-
In other file you can import the `add` value defined in `MathUtils.res`
73+
In other file you can import the `indexOfOpt` value defined in `Core__Array.res`
6974
7075
```rescript
7176
let main = async () => {
72-
let add = await import(MathUtils.add)
73-
let onePlusOne = add(1, 1)
74-
Console.log(onePlusOne)
77+
let indexOfOpt = await import(Core__Array.indexOfOpt)
78+
let index = indexOfOpt([1, 2], 2)
79+
Console.log(index)
7580
}
7681
```
7782
7883
Compiles to:
7984
8085
```javascript
8186
async function main() {
82-
var add = await import("./MathUtils.mjs").then(function(m) {
83-
return m.add;
87+
var add = await import("./Core__Array.mjs").then(function(m) {
88+
return m.indexOfOpt;
8489
});
85-
var onePlusOne = add(1, 1);
86-
console.log(onePlusOne);
90+
var index = indexOfOpt([1, 2], 2);
91+
console.log(index);
8792
}
8893
```
8994
*/

test/IteratorTests.mjs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Generated by ReScript, PLEASE EDIT WITH CARE
2+
3+
import * as Test from "./Test.mjs";
4+
import * as Caml_obj from "rescript/lib/es6/caml_obj.js";
5+
import * as Core__Iterator from "../src/Core__Iterator.mjs";
6+
import * as Core__AsyncIterator from "../src/Core__AsyncIterator.mjs";
7+
8+
var eq = Caml_obj.equal;
9+
10+
var iterator = ((() => {
11+
var array1 = ['a', 'b', 'c'];
12+
var iterator1 = array1[Symbol.iterator]();
13+
return iterator1
14+
})());
15+
16+
var syncResult = {
17+
contents: undefined
18+
};
19+
20+
Core__Iterator.forEach(iterator, (function (v) {
21+
if (v === "b") {
22+
syncResult.contents = "b";
23+
return ;
24+
}
25+
26+
}));
27+
28+
Test.run([
29+
[
30+
"IteratorTests.res",
31+
21,
32+
20,
33+
34
34+
],
35+
"Sync forEach"
36+
], syncResult.contents, eq, "b");
37+
38+
var asyncIterator = ((() => {
39+
var map1 = new Map();
40+
41+
map1.set('first', '1');
42+
map1.set('second', '2');
43+
44+
var iterator1 = map1[Symbol.iterator]();
45+
return iterator1;
46+
})());
47+
48+
var asyncResult = {
49+
contents: undefined
50+
};
51+
52+
await Core__AsyncIterator.forEach(asyncIterator, (function (v) {
53+
if (v !== undefined && v[0] === "second") {
54+
asyncResult.contents = "second";
55+
return ;
56+
}
57+
58+
}));
59+
60+
Test.run([
61+
[
62+
"IteratorTests.res",
63+
44,
64+
20,
65+
35
66+
],
67+
"Async forEach"
68+
], asyncResult.contents, eq, "second");
69+
70+
export {
71+
eq ,
72+
iterator ,
73+
syncResult ,
74+
asyncIterator ,
75+
asyncResult ,
76+
}
77+
/* iterator Not a pure module */

0 commit comments

Comments
 (0)