Skip to content

Commit 36038f8

Browse files
committed
Seq.expand
1 parent 45ce0c7 commit 36038f8

File tree

6 files changed

+55
-1
lines changed

6 files changed

+55
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## Version 4.4.0
2+
3+
- `Seq.expand` is new and similar to `Seq.unfold` but recursively generates a sequence of sequences.
4+
15
## Version 4.3.0
26

37
- `Seq.iterateWhile` generates a sequence until the interation function returns `None`.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ let cons: ('a, t<'a>) => t<'a>
5656
let cycle: t<'a> => t<'a>
5757
let delay: (unit => t<'a>) => t<'a>
5858
let empty: t<'a>
59+
let expand: ('a, 'a => t<('b, 'a)>) => t<t<'b>>
5960
let forever: 'a => t<'a>
6061
let foreverWith: (unit => 'a) => t<'a>
6162
let fromArray: (~start: int=?, ~end: int=?, array<'a>) => t<'a>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@jmagaram/rescript-seq",
3-
"version": "4.3.0",
3+
"version": "4.4.0",
44
"module": "",
55
"description": "Lazy sequences for ReScript.",
66
"keywords": [

src/Seq.res

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,3 +952,9 @@ let iterateWhile = (seed, f) => () => {
952952
}
953953
Next(seed, go(seed))
954954
}
955+
956+
let rec expand = (seed, f) =>
957+
seed
958+
->f
959+
->flatMap(((n, seed)) => expand(seed, f)->map(result => cons(n, result)))
960+
->orElse(empty->once)

src/Seq.resi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ Seq.unfold(1, i => i < 100 ? Some(i, i * 2) : None) // [1, 2, 4, 8, 16, 32, 64]
3535
*/
3636
let unfold: ('seed, 'seed => option<('a, 'seed)>) => t<'a>
3737

38+
/**
39+
`expand(seed, f)` creates a sequence of sequences through a recursive
40+
computation. Similar to `unfold`.
41+
*/
42+
let expand: ('seed, 'seed => t<('a, 'seed)>) => t<t<'a>>
43+
3844
/**
3945
`init(count, f)` initializes a sequence based on a `count` and a function `f`
4046
that is provided index values from 0 up to `count-1`.

tests/Seq__SeqTests.res

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,42 @@ let unfoldTests =
797797
),
798798
])
799799

800+
let expandTests = {
801+
// for a given seed string, return each character and a new seed which is all
802+
// the characters that follow it
803+
let combos = s => {
804+
s
805+
->String.split("")
806+
->Seq.fromArray
807+
->Seq.indexed
808+
->Seq.map(((char, inx)) => (char, s->String.sliceToEnd(~start=inx + 1)))
809+
}
810+
811+
let format = xxx =>
812+
xxx
813+
->Seq.map(xx => xx->Seq.toArray->Array.joinWith(""))
814+
->Seq.toArray
815+
->Seq.fromArray
816+
817+
makeSeqEqualsTests(
818+
~title="expand",
819+
[
820+
(S.expand("abcd", combos)->format, ["abcd", "abd", "acd", "ad", "bcd", "bd", "cd", "d"], ""),
821+
(S.expand("abc", combos)->format, ["abc", "ac", "bc", "c"], ""),
822+
(S.expand("ab", combos)->format, ["ab", "b"], ""),
823+
(S.expand("a", combos)->format, ["a"], ""),
824+
(
825+
S.expand("abcdefghijklmnopqrstuv", combos)
826+
->Seq.last
827+
->Option.map(s => s->Seq.once->format)
828+
->Option.getExn,
829+
["v"],
830+
"millions",
831+
),
832+
],
833+
)
834+
}
835+
800836
let initTests =
801837
makeSeqEqualsTests(
802838
~title="init",
@@ -2229,6 +2265,7 @@ let tests =
22292265
everySomeTests,
22302266
everyTests,
22312267
exactlyOneTests,
2268+
expandTests,
22322269
filterMapiTests,
22332270
filterMapTests,
22342271
filterOkTests,

0 commit comments

Comments
 (0)