From d025edf00a4dfcbd8d013e2f5d7efba3eb6ed2ec Mon Sep 17 00:00:00 2001 From: jmagaram Date: Fri, 17 Mar 2023 16:38:15 -0700 Subject: [PATCH 1/3] better explanation --- src/Core__Array.mjs | 17 ++++++++++++ src/Core__Array.res | 16 +++++++++++ src/Core__Array.resi | 14 ++++++++++ test/ArrayTests.mjs | 64 ++++++++++++++++++++++++++++++++++++++++++++ test/ArrayTests.res | 7 +++++ test/TestSuite.mjs | 3 +++ 6 files changed, 121 insertions(+) diff --git a/src/Core__Array.mjs b/src/Core__Array.mjs index 1560df8f..2b0abb13 100644 --- a/src/Core__Array.mjs +++ b/src/Core__Array.mjs @@ -138,6 +138,22 @@ function findMap(arr, f) { }; } +function fromFormula(state, generator) { + var result = []; + var state$1 = state; + var $$break = false; + while(!$$break) { + var match = Curry._1(generator, state$1); + if (match !== undefined) { + result.push(match[0]); + state$1 = match[1]; + } else { + $$break = true; + } + }; + return result; +} + export { make , fromInitializer , @@ -155,5 +171,6 @@ export { shuffle , shuffleInPlace , findMap , + fromFormula , } /* No side effect */ diff --git a/src/Core__Array.res b/src/Core__Array.res index cd1bda48..97b77157 100644 --- a/src/Core__Array.res +++ b/src/Core__Array.res @@ -214,3 +214,19 @@ let findMap = (arr, f) => { } @send external at: (array<'a>, int) => option<'a> = "at" + +let fromFormula = (state, generator) => { + let result = [] + let state = ref(state) + let break = ref(false) + while !break.contents { + switch generator(state.contents) { + | None => break := true + | Some((item, nextState)) => { + result->push(item) + state := nextState + } + } + } + result +} diff --git a/src/Core__Array.resi b/src/Core__Array.resi index 253f0cf2..05941ead 100644 --- a/src/Core__Array.resi +++ b/src/Core__Array.resi @@ -955,3 +955,17 @@ let findMap: (array<'a>, 'a => option<'b>) => option<'b> */ @send external at: (array<'a>, int) => option<'a> = "at" + +/** +`fromFormula(state, f)` create an array that contains the elements generated by a computation. The function `f` is first passed `state` and then is repeatedly called to build the array. When `f` returns a tuple of `Some(item, state)`, `item` is pushed onto the resultant array, and `state` is fed into the next computation. When `f` returns `None`, the computation is complete and the new array is returned. + +## Examples + +```rescript +let generator = i => i<100 ? Some(i, i*2) : None +1->Array.fromFormula(generator) // [1, 2, 4, 8, 16, 32, 64] +12->Array.fromFormula(generator) // [12, 24, 48, 96] +100->Array.fromFormula(generator) // [] +``` +*/ +let fromFormula: ('state, 'state => option<('a, 'state)>) => array<'a> diff --git a/test/ArrayTests.mjs b/test/ArrayTests.mjs index 7cc4a4c6..884c54b1 100644 --- a/test/ArrayTests.mjs +++ b/test/ArrayTests.mjs @@ -401,7 +401,71 @@ Test.run([ })), eq, undefined); +function generator(i) { + if (i < 100) { + return [ + i, + (i << 1) + ]; + } + +} + +Test.run([ + [ + "ArrayTests.res", + 104, + 20, + 33 + ], + "fromFormula" + ], Core__Array.fromFormula(1, generator), eq, [ + 1, + 2, + 4, + 8, + 16, + 32, + 64 + ]); + +Test.run([ + [ + "ArrayTests.res", + 105, + 20, + 33 + ], + "fromFormula" + ], Core__Array.fromFormula(12, generator), eq, [ + 12, + 24, + 48, + 96 + ]); + +Test.run([ + [ + "ArrayTests.res", + 106, + 20, + 33 + ], + "fromFormula" + ], Core__Array.fromFormula(99, generator), eq, [99]); + +Test.run([ + [ + "ArrayTests.res", + 107, + 20, + 33 + ], + "fromFormula" + ], Core__Array.fromFormula(100, generator), eq, []); + export { eq , + generator , } /* Not a pure module */ diff --git a/test/ArrayTests.res b/test/ArrayTests.res index 40c352f7..e6867796 100644 --- a/test/ArrayTests.res +++ b/test/ArrayTests.res @@ -98,3 +98,10 @@ Test.run( eq, None, ) + +let generator = i => i < 100 ? Some(i, i * 2) : None + +Test.run(__POS_OF__("fromFormula"), Array.fromFormula(1, generator), eq, [1, 2, 4, 8, 16, 32, 64]) +Test.run(__POS_OF__("fromFormula"), Array.fromFormula(12, generator), eq, [12, 24, 48, 96]) +Test.run(__POS_OF__("fromFormula"), Array.fromFormula(99, generator), eq, [99]) +Test.run(__POS_OF__("fromFormula"), Array.fromFormula(100, generator), eq, []) diff --git a/test/TestSuite.mjs b/test/TestSuite.mjs index c968bd8f..05409ad8 100644 --- a/test/TestSuite.mjs +++ b/test/TestSuite.mjs @@ -26,6 +26,8 @@ var Concurrently = PromiseTest.Concurrently; var panicTest = ErrorTests.panicTest; +var generator = ArrayTests.generator; + var eq = IntTests.eq; var $$catch = IntTests.$$catch; @@ -41,6 +43,7 @@ export { Catching , Concurrently , panicTest , + generator , eq , $$catch , } From 1c60657a96a9e7868bd3bbc6f0497d73ee091363 Mon Sep 17 00:00:00 2001 From: jmagaram Date: Sun, 19 Mar 2023 09:42:27 -0700 Subject: [PATCH 2/3] better examples --- src/Core__Array.resi | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Core__Array.resi b/src/Core__Array.resi index 05941ead..bc0f8058 100644 --- a/src/Core__Array.resi +++ b/src/Core__Array.resi @@ -962,10 +962,12 @@ external at: (array<'a>, int) => option<'a> = "at" ## Examples ```rescript -let generator = i => i<100 ? Some(i, i*2) : None -1->Array.fromFormula(generator) // [1, 2, 4, 8, 16, 32, 64] -12->Array.fromFormula(generator) // [12, 24, 48, 96] -100->Array.fromFormula(generator) // [] +let f = i => i<100 ? Some(i, i*2) : None +Array.fromFormula(1, f) // [1, 2, 4, 8, 16, 32, 64] +Array.fromFormula(100, f) // [] + +let g = i => i >= 0.0 ? Some(i, i -. 0.5) : None +Array.fromFormula(3.0, g) // [3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0] ``` */ let fromFormula: ('state, 'state => option<('a, 'state)>) => array<'a> From b02cc1cb766909bb2b9a411f5c4ab2c55e0e7141 Mon Sep 17 00:00:00 2001 From: jmagaram Date: Wed, 22 Mar 2023 11:20:26 -0700 Subject: [PATCH 3/3] better docs --- src/Core__Array.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__Array.resi b/src/Core__Array.resi index bc0f8058..9187d1ff 100644 --- a/src/Core__Array.resi +++ b/src/Core__Array.resi @@ -957,7 +957,7 @@ let findMap: (array<'a>, 'a => option<'b>) => option<'b> external at: (array<'a>, int) => option<'a> = "at" /** -`fromFormula(state, f)` create an array that contains the elements generated by a computation. The function `f` is first passed `state` and then is repeatedly called to build the array. When `f` returns a tuple of `Some(item, state)`, `item` is pushed onto the resultant array, and `state` is fed into the next computation. When `f` returns `None`, the computation is complete and the new array is returned. +`fromFormula(state, f)` creates an array that contains the elements generated by a computation. The function `f` is first passed `state` and then is repeatedly called to build the array. When `f` returns a tuple of `Some(item, state)`, `item` is pushed onto the result array, and `state` is fed into the next computation. When `f` returns `None`, the computation is complete and the new array is returned. ## Examples