Skip to content

Commit 3fbe797

Browse files
zthillusionalsagacity
authored andcommitted
Add iterator and asyncIterator forEach helpers (rescript-lang#175)
* add iterator and asyncIterator forEach helpers * changelog + fix docstrings * fix docstring errors
1 parent 72b99cb commit 3fbe797

11 files changed

+232
-3
lines changed

CHANGELOG.md

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

1213
## 0.7.0
1314

src/Core__AsyncIterator.mjs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,17 @@
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+
import * as Curry from "rescript/lib/es6/curry.js";
4+
5+
async function forEach(iterator, f) {
6+
var iteratorDone = false;
7+
while(!iteratorDone) {
8+
var match = await iterator.next();
9+
Curry._1(f, match.value);
10+
iteratorDone = match.done;
11+
};
12+
}
13+
14+
export {
15+
forEach ,
16+
}
17+
/* 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
@@ -57,3 +57,23 @@ let processMyAsyncIterator = async () => {
5757
*/
5858
@send
5959
external next: t<'a> => promise<value<'a>> = "next"
60+
61+
/**
62+
`forEach(iterator, fn)` consumes all values in the async iterator and runs the callback `fn` for each value.
63+
64+
See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) on MDN.
65+
66+
## Examples
67+
```rescript
68+
// Let's pretend we get an async iterator returning ints from somewhere.
69+
@val external asyncIterator: AsyncIterator.t<int> = "someAsyncIterator"
70+
71+
await asyncIterator->AsyncIterator.forEach(value =>
72+
switch value {
73+
| Some(value) if value > 10 => Console.log("More than 10!")
74+
| _ => ()
75+
}
76+
)
77+
```
78+
*/
79+
let forEach: (t<'a>, option<'a> => unit) => promise<unit>

src/Core__Iterator.mjs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,17 @@
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+
import * as Curry from "rescript/lib/es6/curry.js";
4+
5+
function forEach(iterator, f) {
6+
var iteratorDone = false;
7+
while(!iteratorDone) {
8+
var match = iterator.next();
9+
Curry._1(f, match.value);
10+
iteratorDone = match.done;
11+
};
12+
}
13+
14+
export {
15+
forEach ,
16+
}
17+
/* 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: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript
3030

3131
## Examples
3232
```rescript
33+
@val external someIterator: Iterator.t<int> = "someIterator"
34+
3335
// Pulls out the next value of the iterator
3436
let {done, value} = someIterator->Iterator.next
3537
```
@@ -78,3 +80,22 @@ Console.log(mapKeysAsArray) // Logs [7, 8] to the console.
7880
```
7981
*/
8082
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

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 */

test/IteratorTests.res

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
open RescriptCore
2+
3+
let eq = (a, b) => a == b
4+
5+
let iterator: Iterator.t<string> = %raw(`
6+
(() => {
7+
var array1 = ['a', 'b', 'c'];
8+
var iterator1 = array1[Symbol.iterator]();
9+
return iterator1
10+
})()
11+
`)
12+
13+
let syncResult = ref(None)
14+
15+
iterator->Iterator.forEach(v => {
16+
if v === Some("b") {
17+
syncResult.contents = Some("b")
18+
}
19+
})
20+
21+
Test.run(__POS_OF__("Sync forEach"), syncResult.contents, eq, Some("b"))
22+
23+
let asyncIterator: AsyncIterator.t<(string, string)> = %raw(`
24+
(() => {
25+
var map1 = new Map();
26+
27+
map1.set('first', '1');
28+
map1.set('second', '2');
29+
30+
var iterator1 = map1[Symbol.iterator]();
31+
return iterator1;
32+
})()
33+
`)
34+
35+
let asyncResult = ref(None)
36+
37+
await asyncIterator->AsyncIterator.forEach(v => {
38+
switch v {
39+
| Some(("second", _value)) => asyncResult.contents = Some("second")
40+
| _ => ()
41+
}
42+
})
43+
44+
Test.run(__POS_OF__("Async forEach"), asyncResult.contents, eq, Some("second"))

test/TestSuite.mjs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
// Generated by ReScript, PLEASE EDIT WITH CARE
22

33
import * as IntTests from "./IntTests.mjs";
4+
import * as DictTests from "./DictTests.mjs";
45
import * as TestTests from "./TestTests.mjs";
56
import * as ArrayTests from "./ArrayTests.mjs";
67
import * as ErrorTests from "./ErrorTests.mjs";
78
import * as FloatTests from "./FloatTests.mjs";
89
import * as ObjectTests from "./ObjectTests.mjs";
910
import * as PromiseTest from "./PromiseTest.mjs";
1011
import * as ResultTests from "./ResultTests.mjs";
12+
import * as IteratorTests from "./IteratorTests.mjs";
1113
import * as TypedArrayTests from "./TypedArrayTests.mjs";
1214

1315
var bign = TestTests.bign;
@@ -64,7 +66,15 @@ var areSame = TypedArrayTests.areSame;
6466

6567
var o = TypedArrayTests.o;
6668

67-
var eq = FloatTests.eq;
69+
var eq = IteratorTests.eq;
70+
71+
var iterator = IteratorTests.iterator;
72+
73+
var syncResult = IteratorTests.syncResult;
74+
75+
var asyncIterator = IteratorTests.asyncIterator;
76+
77+
var asyncResult = IteratorTests.asyncResult;
6878

6979
export {
7080
bign ,
@@ -95,5 +105,9 @@ export {
95105
areSame ,
96106
o ,
97107
eq ,
108+
iterator ,
109+
syncResult ,
110+
asyncIterator ,
111+
asyncResult ,
98112
}
99113
/* IntTests Not a pure module */

test/TestSuite.res

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ include ObjectTests
77
include ResultTests
88
include TypedArrayTests
99
include FloatTests
10+
include DictTests
11+
include IteratorTests

0 commit comments

Comments
 (0)