Polymorphic immutable sequences.
The interface is the same as Seq
. The difference is that delayed
sequences avoid allocating temporary intermediate arrays, to improve
performance. In general, most pipelines of operations such as
map
, zip
, reduce
, scan
, filter
, and flatten
will be more
efficient with DelayedSeq
than with Seq
.
The intended usage is to first convert a sequence to a delayed version
with DelayedSeq.fromArraySeq
, then perform a pipeline, and finally
(if there is some output sequence) convert the result back to a normal
sequence with DelayedSeq.toArraySeq
.
This implementation is based on this paper:
Parallel Block-Delayed Sequences. Sam Westrick, Mike Rainey, Daniel Anderson, Guy E. Blelloch. PPoPP'22
structure DS = DelayedSeq
(** Compute the sum of non-negative elements of `s`.
* We don't need to use DS.toArraySeq at the end, because
* the result is just an integer.
*)
fun sumNonNegative (s: int Seq.t) =
DS.reduce op+ 0
(DS.map (fn x => Int.max (0, x))
(DS.fromArraySeq s))
(** For example:
* evenMultiplesUpto 21 [3,5] ==> [6,12,18,10,20]
*)
fun evenMultiplesUpto (n: int) (s: int Seq.t) =
let
fun multiples x =
let
val numMultiples = n div x - 1
in
DS.tabulate (fn i => (i+2)*x) numMultiples
end
in
DS.toArraySeq (DS.filter (fn x => x mod 2 = 0)
(DS.flatten (DS.map multiples (DS.fromArraySeq s))))
end