Skip to content

Commit

Permalink
add make and convenience functions for async iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
zth committed Aug 26, 2024
1 parent 22642ea commit fe3f94e
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 5 deletions.
27 changes: 27 additions & 0 deletions src/Core__AsyncIterator.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
// Generated by ReScript, PLEASE EDIT WITH CARE

import * as Caml_option from "rescript/lib/es6/caml_option.js";

function value(v) {
return {
done: false,
value: Caml_option.some(v)
};
}

function done(finalValue) {
return {
done: true,
value: finalValue
};
}

async function forEach(iterator, f) {
var iteratorDone = false;
Expand All @@ -10,7 +25,19 @@ async function forEach(iterator, f) {
};
}

var make = (function makeAsyncIterator(next) {
return {
next,
[Symbol.asyncIterator]() {
return this;
}
}
});

export {
make ,
value ,
done ,
forEach ,
}
/* No side effect */
19 changes: 19 additions & 0 deletions src/Core__AsyncIterator.res
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ type value<'a> = {
value: option<'a>,
}

let value = v => {
done: false,
value: Some(v),
}

let done = (~finalValue=?) => {
done: true,
value: finalValue,
}

@send external next: t<'a> => promise<value<'a>> = "next"

let forEach = async (iterator, f) => {
Expand All @@ -16,3 +26,12 @@ let forEach = async (iterator, f) => {
iteratorDone := done
}
}

let make: (unit => promise<value<'value>>) => t<'value> = %raw(`function makeAsyncIterator(next) {
return {
next,
[Symbol.asyncIterator]() {
return this;
}
}
}`)
82 changes: 81 additions & 1 deletion src/Core__AsyncIterator.resi
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,86 @@ type value<'a> = {
value: option<'a>,
}

/**
`make(nextFn)`
Creates an async iterator from a function that returns the next value of the iterator.
## Examples
- A simple example, creating an async iterator that returns 1, 2, 3:
```rescript
let context = ref(0)
let asyncIterator = AsyncIterator.make(async () => {
let currentValue = context.contents
// Increment current value
context := currentValue + 1
{
value: Some(currentValue),
done: currentValue >= 3
}
})
// This will log 1, 2, 3
await asyncIterator->AsyncIterator.forEach(value =>
switch value {
| Some(value) => Console.log(value)
| None => ()
}
)
```
*/
let make: (unit => promise<value<'value>>) => t<'value>

/**
`value(value)`
Shorthand for creating a value object with the provided value, and the `done` property set to false.
## Examples
```rescript
let context = ref(0)
let asyncIterator = AsyncIterator.make(async () => {
let currentValue = context.contents
// Increment current value
context := currentValue + 1
if currentValue >= 3 {
AsyncIterator.done()
} else {
AsyncIterator.value(currentValue)
}
})
```
*/
let value: 'value => value<'value>

/**
`done(~finalValue=?)`
Shorthand for creating a value object with the `done` property set to true, and the provided value as the final value, if any.
## Examples
```rescript
let context = ref(0)
let asyncIterator = AsyncIterator.make(async () => {
let currentValue = context.contents
// Increment current value
context := currentValue + 1
if currentValue >= 3 {
AsyncIterator.done()
} else {
AsyncIterator.value(currentValue)
}
})
```
*/
let done: (~finalValue: 'value=?) => value<'value>

/**
`next(asyncIterator)`
Expand All @@ -30,7 +110,7 @@ See [async iterator protocols](https://developer.mozilla.org/en-US/docs/Web/Java
- A simple example, getting the next value:
```rescript
@val external asyncIterator: AsyncIterator.t<int> = "someAsyncIterator"
let {AsyncIterator.done, value} = await asyncIterator->AsyncIterator.next
let {done, value} = await asyncIterator->AsyncIterator.next
```
- Complete example, including looping over all values:
Expand Down
38 changes: 37 additions & 1 deletion test/IteratorTests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,47 @@ Test.run([
"Async forEach"
], asyncResult.contents, eq, "second");

var asyncResult$1 = {
contents: undefined
};

var count = {
contents: 0
};

var asyncIterator$1 = Core__AsyncIterator.make(async function () {
var currentCount = count.contents;
count.contents = currentCount + 1 | 0;
if (currentCount === 3) {
return Core__AsyncIterator.done(currentCount);
} else {
return Core__AsyncIterator.value(currentCount);
}
});

await Core__AsyncIterator.forEach(asyncIterator$1, (function (v) {
if (v === 3) {
asyncResult$1.contents = "done";
} else {
console.log("next..");
}
}));

Test.run([
[
"IteratorTests.res",
69,
20,
54
],
"Creating your own async iterator"
], asyncResult$1.contents, eq, "done");

export {
eq ,
iterator ,
syncResult ,
asyncIterator ,
asyncResult ,
asyncIterator$1 as asyncIterator,
}
/* iterator Not a pure module */
25 changes: 25 additions & 0 deletions test/IteratorTests.res
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,28 @@ await asyncIterator->AsyncIterator.forEach(v => {
})

Test.run(__POS_OF__("Async forEach"), asyncResult.contents, eq, Some("second"))

%%private(
let asyncResult = ref(None)
let count = ref(0)
)

let asyncIterator = AsyncIterator.make(async () => {
let currentCount = count.contents
count := currentCount + 1

if currentCount === 3 {
AsyncIterator.done(~finalValue=currentCount)
} else {
AsyncIterator.value(currentCount)
}
})

await asyncIterator->AsyncIterator.forEach(v => {
switch v {
| Some(3) => asyncResult.contents = Some("done")
| _ => Console.log("next..")
}
})

Test.run(__POS_OF__("Creating your own async iterator"), asyncResult.contents, eq, Some("done"))
6 changes: 3 additions & 3 deletions test/TestSuite.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ var iterator = IteratorTests.iterator;

var syncResult = IteratorTests.syncResult;

var asyncIterator = IteratorTests.asyncIterator;

var asyncResult = IteratorTests.asyncResult;

var asyncIterator = IteratorTests.asyncIterator;

export {
bign ,
TestError ,
Expand Down Expand Up @@ -115,7 +115,7 @@ export {
eq ,
iterator ,
syncResult ,
asyncIterator ,
asyncResult ,
asyncIterator ,
}
/* IntTests Not a pure module */

0 comments on commit fe3f94e

Please sign in to comment.