A sequence is a list whose elements are computed only on demand, similar to JavaScript iterables. Sequences are produced and transformed lazily (one element at a time) rather than eagerly (all at once). This allows constructing conceptually infinite sequences. When your data is an array, call fromArray to create a sequence, which is just a lightweight function that iterates over its values. And then you can use the sequence functions to analyze and transform it with far more flexibility and power than what is possible with the built-in array functions. Sequences can sometimes provide better performance than an array when not all elements are used.
Sequences are in the standard libraries of F#, OCaml, Rust, .net, Haskell, and Python. There are JavaScript libraries to consume iterables, and a Stage 3 TC39 proposal to add iterator helpers.
This is a full-featured package to create and consume sequences in ReScript. Highlights:
- Enables more elegant and concise solutions than using imperative code and arrays
- 100+ functions, chosen by researching the best from other libraries
- API documentation
- Comprehensive test suite
- Written 100% in ReScript; look at the code and tests to see how it works.
- Create sequences with
fromArray,range,unfold,cycle,permutations,replicate, ... - Transform with
map,filter,split,takeUntil,scan,tap,pairwise... - Combine with
zip,map3,allPairs,sortedMerge,interleave... - Calculate with
reduceUntil,maxBy,every,findMap,isSortedBy,toArray...
See code examples.
npm install @jmagaram/rescript-seqAdd to your rescript.json...
{
...
+ "bs-dependencies": ["@jmagaram/rescript-seq"]
}All functions are in the Seq module. See other examples.
["a", "b", "c", "d"]
->Seq.fromArray->Seq.combinations(3)
->Seq.map(((_, combo)) =>combo->Seq.join(""))
->Seq.join(", ")
->Console.log// a, b, ba, c, ca, cb, cba, d, da, db, dba, dc, dca, dcbtypet<'a> // A lazy sequence of 'a// Constructletcombinations: (t<'a>, int) =>t<(int, t<'a>)>
letcons: ('a, t<'a>) =>t<'a>
letcycle: t<'a> =>t<'a>
letdelay: (unit=>t<'a>) =>t<'a>
letempty: t<'a>
letunfoldMany: ('a, 'a=>t<('b, 'a)>) =>t<t<'b>>
letforever: 'a=>t<'a>
letforeverWith: (unit=>'a) =>t<'a>
letfromArray: (~start: int=?, ~end: int=?, array<'a>) =>t<'a>
letfromList: list<'a> =>t<'a>
letinit: (int, int=>'a) =>t<'a>
letiterate: ('a, 'a=>'a) =>t<'a>
letiterateWhile: ('a, 'a=>option<'a>) =>t<'a>
letonce: 'a=>t<'a>
letonceWith: (unit=>'a) =>t<'a>
letpermutations: (t<'a>, int) =>t<(int, t<'a>)>
letrange: (int, int) =>t<int>
letrangeMap: (int, int, int=>'a) =>t<'a>
letreplicate: ('a, int) =>t<'a>
letreplicateWith: (unit=>'a, int) =>t<'a>
letunfold: ('a, 'a=>option<('b, 'a)>) =>t<'b>
// Transformletcache: t<'a> =>t<'a>
letchunkBySize: (t<'a>, int) =>t<array<'a>>
letdrop: (t<'a>, int) =>t<'a>
letdropLast: (t<'a>, int) =>t<'a>
letdropUntil: (t<'a>, 'a=>bool) =>t<'a>
letdropWhile: (t<'a>, 'a=>bool) =>t<'a>
letfilter: (t<'a>, 'a=>bool) =>t<'a>
letfilteri: (t<'a>, ('a, int) =>bool) =>t<'a>
letfilterMap: (t<'a>, 'a=>option<'b>) =>t<'b>
letfilterMapi: (t<'a>, ('a, int) =>option<'b>) =>t<'b>
letfilterOk: t<result<'a, 'b>> =>t<'a>
letfilterSome: t<option<'a>> =>t<'a>
letflatMap: (t<'a>, 'a=>t<'b>) =>t<'b>
letflatten: t<t<'a>> =>t<'a>
letindexed: t<'a> =>t<('a, int)>
letintersperse: (t<'a>, 'a) =>t<'a>
letintersperseWith: (t<'a>, unit=>'a) =>t<'a>
letmap: (t<'a>, 'a=>'b) =>t<'b>
letmapi: (t<'a>, ('a, int) =>'b) =>t<'b>
letneighbors: t<'a> =>t<(option<'a>, 'a, option<'a>)>
letpairAhead: t<'a> =>t<('a, option<'a>)>
letpairBehind: t<'a> =>t<(option<'a>, 'a)>
letpairwise: t<'a> =>t<('a, 'a)>
letprefixSum: (t<'a>, ('a, 'a) =>'a) =>t<'a>
letreverse: t<'a> =>t<'a>
letscan: (t<'a>, 'b, ('b, 'a) =>'b) =>t<'b>
letsortBy: (t<'a>, ('a, 'a) =>float) =>t<'a>
letsplit: (t<'a>, 'a=>'b, ('b, 'a) =>option<'b>) =>t<'b>
lettail: t<'a> =>t<'a>
lettails: t<'a> =>t<t<'a>>
lettake: (t<'a>, int) =>t<'a>
lettakeUntil: (t<'a>, 'a=>bool) =>t<'a>
lettakeWhile: (t<'a>, 'a=>bool) =>t<'a>
lettap: (t<'a>, 'a=>unit) =>t<'a>
letwindow: (t<'a>, int) =>t<array<'a>>
// CombineletallPairs: (t<'a>, t<'b>) =>t<('a, 'b)>
letappend: (t<'a>, t<'a>) =>t<'a>
letconcat: (t<'a>, t<'a>) =>t<'a>
letinterleave: (t<'a>, t<'a>) =>t<'a>
letmap2: (t<'a>, t<'b>, ('a, 'b) =>'c) =>t<'c>
letmap3: (t<'a>, t<'b>, t<'c>, ('a, 'b, 'c) =>'d) =>t<'d>
letmap4: (t<'a>, t<'b>, t<'c>, t<'d>, ('a, 'b, 'c, 'd) =>'e) =>t<'e>
letmap5: (t<'a>, t<'b>, t<'c>, t<'d>, t<'e>, ('a, 'b, 'c, 'd, 'e) =>'f) =>t<'f>
letorElse: (t<'a>, t<'a>) =>t<'a>
letprepend: (t<'a>, t<'a>) =>t<'a>
letsortedMerge: (t<'a>, t<'a>, ('a, 'a) =>float) =>t<'a>
letzip: (t<'a>, t<'b>) =>t<('a, 'b)>
letzip3: (t<'a>, t<'b>, t<'c>) =>t<('a, 'b, 'c)>
letzip4: (t<'a>, t<'b>, t<'c>, t<'d>) =>t<('a, 'b, 'c, 'd)>
letzip5: (t<'a>, t<'b>, t<'c>, t<'d>, t<'e>) =>t<('a, 'b, 'c, 'd, 'e)>
// Reduce, consume, and calculateletat: (t<'a>, int) =>option<'a>
letcompare: (t<'a>, t<'b>, ('a, 'b) =>int) =>intletconsume: t<'a> =>unitletequals: (t<'a>, t<'b>, ('a, 'b) =>bool) =>boolletevery: (t<'a>, 'a=>bool) =>boolleteveryOk: t<result<'a, 'b>> =>result<t<'a>, 'b>
leteverySome: t<option<'a>> =>option<t<'a>>
letexactlyOne: t<'a> =>option<'a>
letfind: (t<'a>, 'a=>bool) =>option<'a>
letfindLast: (t<'a>, 'a=>bool) =>option<'a>
letfindMap: (t<'a>, 'a=>option<'b>) =>option<'b>
letfindMapLast: (t<'a>, 'a=>option<'b>) =>option<'b>
letforEach: (t<'a>, 'a=>unit) =>unitletforEachi: (t<'a>, ('a, int) =>unit) =>unitlethead: t<'a> =>option<'a>
letisEmpty: t<'a> =>boolletisSortedBy: (t<'a>, ('a, 'a) =>float) =>boolletjoin: t<string> =>stringletlast: t<'a> =>option<'a>
letlength: t<'a> =>intletmaxBy: (t<'a>, ('a, 'a) =>float) =>option<'a>
letminBy: (t<'a>, ('a, 'a) =>float) =>option<'a>
letreduce: (t<'a>, 'b, ('b, 'a) =>'b) =>'bletreduceUntil: (t<'a>, 'b, ('b, 'a) =>'b, 'b=>bool) =>'bletreduceWhile: (t<'a>, 'b, ('b, 'a) =>'b, 'b=>bool) =>option<'b>
letsome: (t<'a>, 'a=>bool) =>boolletsumBy: (t<'a>, ('a, 'a) =>'a) =>option<'a>
lettoArray: t<'a> =>array<'a>
lettoList: t<'a> =>list<'a>
lettoOption: t<'a> =>option<t<'a>>
letuncons: t<'a> =>option<('a, t<'a>)>