diff --git a/CHANGELOG.md b/CHANGELOG.md index 222470b5..9b7f3989 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Next version - Optimize compare and equal functions. https://github.com/rescript-association/rescript-core/pull/238 +- Add `make` and `done` + `value` functions to `AsyncIterator`. https://github.com/rescript-association/rescript-core/pull/243 ## 1.5.2 diff --git a/src/Core__AsyncIterator.mjs b/src/Core__AsyncIterator.mjs index 9c43464a..240039c8 100644 --- a/src/Core__AsyncIterator.mjs +++ b/src/Core__AsyncIterator.mjs @@ -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; @@ -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 */ diff --git a/src/Core__AsyncIterator.res b/src/Core__AsyncIterator.res index 4781fbe7..56abad28 100644 --- a/src/Core__AsyncIterator.res +++ b/src/Core__AsyncIterator.res @@ -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> = "next" let forEach = async (iterator, f) => { @@ -16,3 +26,12 @@ let forEach = async (iterator, f) => { iteratorDone := done } } + +let make: (unit => promise>) => t<'value> = %raw(`function makeAsyncIterator(next) { + return { + next, + [Symbol.asyncIterator]() { + return this; + } + } +}`) diff --git a/src/Core__AsyncIterator.resi b/src/Core__AsyncIterator.resi index 5644838b..bbe8de3b 100644 --- a/src/Core__AsyncIterator.resi +++ b/src/Core__AsyncIterator.resi @@ -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 + + { + AsyncIterator.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>) => 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)` @@ -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 = "someAsyncIterator" -let {AsyncIterator.done, value} = await asyncIterator->AsyncIterator.next +let value = await asyncIterator->AsyncIterator.next ``` - Complete example, including looping over all values: diff --git a/test/IteratorTests.mjs b/test/IteratorTests.mjs index 55b008a7..c40b9739 100644 --- a/test/IteratorTests.mjs +++ b/test/IteratorTests.mjs @@ -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 */ diff --git a/test/IteratorTests.res b/test/IteratorTests.res index 29a22eac..902df8ae 100644 --- a/test/IteratorTests.res +++ b/test/IteratorTests.res @@ -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")) diff --git a/test/TestSuite.mjs b/test/TestSuite.mjs index e0ee5b0b..00c9cb7d 100644 --- a/test/TestSuite.mjs +++ b/test/TestSuite.mjs @@ -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 , @@ -115,7 +115,7 @@ export { eq , iterator , syncResult , - asyncIterator , asyncResult , + asyncIterator , } /* IntTests Not a pure module */