package batteries
Install
Dune Dependency
Authors
Maintainers
Sources
md5=ea26b5c72e6731e59d856626049cca4d
sha512=55975b62c26f6db77433a3ac31f97af609fc6789bb62ac38b267249c78fd44ff37fe81901f1cf560857b9493a6046dd37b0d1c0234c66bd59e52843aac3ce6cb
doc/batteries.unthreaded/BatSeq/index.html
Module BatSeq
Source
Sequence of elements
A sequence represents a collection of elements, for which you never construct the complete representation.
Basically you should use a sequence when you would prefer using a list or a lazy-list but constructing the whole list explicitly would explode your memory.
All functions returning a sequence operates in time and space O(1).
Note that if you want a ``consumable sequence'', you should prefer using enumerations (from module BatEnum
).
include BatInterfaces.Mappable with type 'a mappable = 'a t
enum s
returns the enumeration of all element of s
.
Since enumerations are consumable and sequence are not, it is not possible to have the inverse operations, i.e. of_enum
Base operations
Returns the first element of the sequence or raise Invalid_argument
if the sequence is empty.
Returns the sequence without its first elements or raise Invalid_argument
if the sequence is empty.
Returns the last element of the sequence, or raise Invalid_argument
if the sequence is empty.
at l n
returns the element at index n
(starting from 0
) in the sequence l
or raise Invalid_argument
is the index is outside of l
bounds.
append s1 s2
returns the sequence which first returns all elements of s1
then all elements of s2
.
concat s
returns the sequence which returns all the elements of all the elements of s
, in the same order.
Constructors
make n e
returns the sequence of length n
where all elements are e
Build a sequence from a step function and an initial value. unfold f u
returns empty
if f u
returns None
, or fun () -> Cons (x, unfold f y)
if f u
returns Some (x, y)
.
For example, unfold (function [] -> None | h::t -> Some (h,t)) l
is equivalent to List.to_seq l
.
Map each element to a subsequence, then return each element of this sub-sequence in turn. This transformation is lazy, it only applies when the result is traversed.
Iterators
iter f s
applies f
to all the elements of the sequence. Eager.
map f s
returns the sequence where elements are elements of s
mapped with f
. Lazy.
fold_left f a (cons b0 (... bn))
is f (... (f (f a b0) b1) ...) bn
. Tail-recursive, eager.
fold_right f (cons a0 (cons a1 (cons a2 ...))) b
is f a0 (f a1 (f a2 ...))
. Not tail-recursive, eager.
equal ~eq s1 s2
compares elements of s1
and s2
pairwise using eq
Sequence scanning
Most functions in the following sections have a shortcut semantic similar to the behavior of the usual (&&) and (||) operators : they will force the sequence until they find an satisfying element, and then return immediately.
For example, for_all
will only diverge if the sequence begins with an infinite number of true elements --- elements for which the predicate p
returns true
.
mem a l
is true if and only if a
is equal to an element of l
. Eager, shortcut.
Sequence searching
filter p s
returns the sequence of elements of s
satisfying p
. Lazy.
Note filter is lazy in that it returns a lazy sequence, but each element in the result is eagerly searched in the input sequence. Therefore, the access to a given element in the result will diverge if it is preceded, in the input sequence, by infinitely many false elements (elements on which the predicate p
returns false
).
Other functions that may drop an unbound number of elements (filter_map
, take_while
, etc.) have the same behavior.
filter_map f s
returns the sequence of elements filtered and mapped by f
. Lazy.
Association sequences
assoc a s
returns the value associated with key a
in the sequence of pairs s
. Eager, shortcut.
Sequence transformations
Sequence of pairs
Transform a pair of sequences into a sequence of pairs. Lazy.
Printing
val print :
?first:string ->
?last:string ->
?sep:string ->
('a BatInnerIO.output -> 'b -> unit) ->
'a BatInnerIO.output ->
'b t ->
unit
Print the contents of a sequence
val to_buffer :
?first:string ->
?last:string ->
?sep:string ->
('a -> string) ->
Buffer.t ->
(unit -> 'a node) ->
unit
Convert a sequence to a string in the given buffer; eager.
val to_string :
?first:string ->
?last:string ->
?sep:string ->
('a -> string) ->
'a t ->
string
Convert the sequence to a string; eager.
val of_string :
?first:string ->
?last:string ->
?sep:string ->
(string -> 'a) ->
string ->
'a t
Create a sequence by parsing a string.
Infix operators matching those provided by BatEnum.Infix
include module type of Infix
is_empty xs
determines whether the sequence xs
is empty.
It is recommended that the sequence xs
be persistent. Indeed, is_empty xs
demands the head of the sequence xs
, so, if xs
is ephemeral, it may be the case that xs
cannot be used any more after this call has taken place.
If xs
is empty, then uncons xs
is None
.
If xs
is nonempty, then uncons xs
is Some (head xs, tail xs)
, that is, a pair of the head and tail of the sequence xs
.
This equivalence holds if xs
is persistent. If xs
is ephemeral, then uncons
must be preferred over separate calls to head
and tail
, which would cause xs
to be queried twice.
length xs
is the length of the sequence xs
.
The sequence xs
must be finite.
iteri f xs
invokes f i x
successively for every element x
located at index i
in the sequence xs
.
It terminates only if the sequence xs
is finite.
iteri f xs
is equivalent to iter (fun (i, x) -> f i x) (zip (ints 0) xs)
.
fold_lefti f _ xs
invokes f _ i x
successively for every element x
located at index i
of the sequence xs
.
An accumulator of type 'b
is threaded through the calls to f
.
It terminates only if the sequence xs
is finite.
fold_lefti f accu xs
is equivalent to fold_left (fun accu (i, x) -> f accu i x) accu (zip (ints 0) xs)
.
for_all p xs
determines whether all elements x
of the sequence xs
satisfy p x
.
The sequence xs
must be finite.
exists xs p
determines whether at least one element x
of the sequence xs
satisfies p x
.
The sequence xs
must be finite.
find p xs
returns Some x
, where x
is the first element of the sequence xs
that satisfies p x
, if there is such an element.
It returns None
if there is no such element.
The sequence xs
must be finite.
find_map f xs
returns Some y
, where x
is the first element of the sequence xs
such that f x = Some _
, if there is such an element, and where y
is defined by f x = Some y
.
It returns None
if there is no such element.
The sequence xs
must be finite.
iter2 f xs ys
invokes f x y
successively for every pair (x, y)
of elements drawn synchronously from the sequences xs
and ys
.
If the sequences xs
and ys
have different lengths, then iteration stops as soon as one sequence is exhausted; the excess elements in the other sequence are ignored.
Iteration terminates only if at least one of the sequences xs
and ys
is finite.
iter2 f xs ys
is equivalent to iter (fun (x, y) -> f x y) (zip xs ys)
.
fold_left2 f _ xs ys
invokes f _ x y
successively for every pair (x, y)
of elements drawn synchronously from the sequences xs
and ys
.
An accumulator of type 'a
is threaded through the calls to f
.
If the sequences xs
and ys
have different lengths, then iteration stops as soon as one sequence is exhausted; the excess elements in the other sequence are ignored.
Iteration terminates only if at least one of the sequences xs
and ys
is finite.
fold_left2 f accu xs ys
is equivalent to fold_left (fun accu (x, y) -> f accu x y) (zip xs ys)
.
for_all2 p xs ys
determines whether all pairs (x, y)
of elements drawn synchronously from the sequences xs
and ys
satisfy p x y
.
If the sequences xs
and ys
have different lengths, then iteration stops as soon as one sequence is exhausted; the excess elements in the other sequence are ignored. In particular, if xs
or ys
is empty, then for_all2 p xs ys
is true. This is where for_all2
and equal
differ: equal eq xs ys
can be true only if xs
and ys
have the same length.
At least one of the sequences xs
and ys
must be finite.
for_all2 p xs ys
is equivalent to for_all (fun b -> b) (map2 p xs ys)
.
exists2 p xs ys
determines whether some pair (x, y)
of elements drawn synchronously from the sequences xs
and ys
satisfies p x y
.
If the sequences xs
and ys
have different lengths, then iteration must stop as soon as one sequence is exhausted; the excess elements in the other sequence are ignored.
At least one of the sequences xs
and ys
must be finite.
exists2 p xs ys
is equivalent to exists (fun b -> b) (map2 p xs ys)
.
Provided the function eq
defines an equality on elements, equal eq xs ys
determines whether the sequences xs
and ys
are pointwise equal.
At least one of the sequences xs
and ys
must be finite.
Provided the function cmp
defines a preorder on elements, compare cmp xs ys
compares the sequences xs
and ys
according to the lexicographic preorder.
For more details on comparison functions, see Array.sort
.
At least one of the sequences xs
and ys
must be finite.
init n f
is the sequence f 0; f 1; ...; f (n-1)
.
n
must be nonnegative.
If desired, the infinite sequence f 0; f 1; ...
can be defined as map f (ints 0)
.
repeat x
is the infinite sequence where the element x
is repeated indefinitely.
repeat x
is equivalent to cycle (return x)
.
forever f
is an infinite sequence where every element is produced (on demand) by the function call f()
.
For instance, forever Random.bool
is an infinite sequence of random bits.
forever f
is equivalent to map f (repeat ())
.
cycle xs
is the infinite sequence that consists of an infinite number of repetitions of the sequence xs
.
If xs
is an empty sequence, then cycle xs
is empty as well.
Consuming (a prefix of) the sequence cycle xs
once can cause the sequence xs
to be consumed more than once. Therefore, xs
must be persistent.
iterate f x
is the infinite sequence whose elements are x
, f x
, f (f x)
, and so on.
In other words, it is the orbit of the function f
, starting at x
.
mapi
is analogous to map
, but applies the function f
to an index and an element.
mapi f xs
is equivalent to map2 f (ints 0) xs
.
If xs
is a sequence [x0; x1; x2; ...]
, then scan f a0 xs
is a sequence of accumulators [a0; a1; a2; ...]
where a1
is f a0 x0
, a2
is f a1 x1
, and so on.
Thus, scan f a0 xs
is conceptually related to fold_left f a0 xs
. However, instead of performing an eager iteration and immediately returning the final accumulator, it returns a sequence of accumulators.
For instance, scan (+) 0
transforms a sequence of integers into the sequence of its partial sums.
If xs
has length n
then scan f a0 xs
has length n+1
.
take n xs
is the sequence of the first n
elements of xs
.
If xs
has fewer than n
elements, then take n xs
is equivalent to xs
.
n
must be nonnegative.
drop n xs
is the sequence xs
, deprived of its first n
elements.
If xs
has fewer than n
elements, then drop n xs
is empty.
n
must be nonnegative.
drop
is lazy: the first n+1
elements of the sequence xs
are demanded only when the first element of drop n xs
is demanded. For this reason, drop 1 xs
is not equivalent to tail xs
, which queries xs
immediately.
take_while p xs
is the longest prefix of the sequence xs
where every element x
satisfies p x
.
drop_while p xs
is the sequence xs
, deprived of the prefix take_while p xs
.
Provided the function eq
defines an equality on elements, group eq xs
is the sequence of the maximal runs of adjacent duplicate elements of the sequence xs
.
Every element of group eq xs
is a nonempty sequence of equal elements.
The concatenation concat (group eq xs)
is equal to xs
.
Consuming group eq xs
, and consuming the sequences that it contains, can cause xs
to be consumed more than once. Therefore, xs
must be persistent.
The sequence memoize xs
has the same elements as the sequence xs
.
Regardless of whether xs
is ephemeral or persistent, memoize xs
is persistent: even if it is queried several times, xs
is queried at most once.
The construction of the sequence memoize xs
internally relies on suspensions provided by the module Lazy
. These suspensions are not thread-safe. Therefore, the sequence memoize xs
must not be queried by multiple threads concurrently.
This exception is raised when a sequence returned by once
(or a suffix of it) is queried more than once.
The sequence once xs
has the same elements as the sequence xs
.
Regardless of whether xs
is ephemeral or persistent, once xs
is an ephemeral sequence: it can be queried at most once. If it (or a suffix of it) is queried more than once, then the exception Forced_twice
is raised. This can be useful, while debugging or testing, to ensure that a sequence is consumed at most once.
If xss
is a matrix (a sequence of rows), then transpose xss
is the sequence of the columns of the matrix xss
.
The rows of the matrix xss
are not required to have the same length.
The matrix xss
is not required to be finite (in either direction).
The matrix xss
must be persistent.
zip xs ys
is the sequence of pairs (x, y)
drawn synchronously from the sequences xs
and ys
.
If the sequences xs
and ys
have different lengths, then the sequence ends as soon as one sequence is exhausted; the excess elements in the other sequence are ignored.
zip xs ys
is equivalent to map2 (fun a b -> (a, b)) xs ys
.
map2 f xs ys
is the sequence of the elements f x y
, where the pairs (x, y)
are drawn synchronously from the sequences xs
and ys
.
If the sequences xs
and ys
have different lengths, then the sequence ends as soon as one sequence is exhausted; the excess elements in the other sequence are ignored.
map2 f xs ys
is equivalent to map (fun (x, y) -> f x y) (zip xs ys)
.
interleave xs ys
is the sequence that begins with the first element of xs
, continues with the first element of ys
, and so on.
When one of the sequences xs
and ys
is exhausted, interleave xs ys
continues with the rest of the other sequence.
If the sequences xs
and ys
are sorted according to the total preorder cmp
, then sorted_merge cmp xs ys
is the sorted sequence obtained by merging the sequences xs
and ys
.
For more details on comparison functions, see Array.sort
.
product xs ys
is the Cartesian product of the sequences xs
and ys
.
For every element x
of xs
and for every element y
of ys
, the pair (x, y)
appears once as an element of product xs ys
.
The order in which the pairs appear is unspecified.
The sequences xs
and ys
are not required to be finite.
The sequences xs
and ys
must be persistent.
The sequence map_product f xs ys
is the image through f
of the Cartesian product of the sequences xs
and ys
.
For every element x
of xs
and for every element y
of ys
, the element f x y
appears once as an element of map_product f xs ys
.
The order in which these elements appear is unspecified.
The sequences xs
and ys
are not required to be finite.
The sequences xs
and ys
must be persistent.
map_product f xs ys
is equivalent to map (fun (x, y) -> f x y) (product xs ys)
.
unzip
transforms a sequence of pairs into a pair of sequences.
unzip xs
is equivalent to (map fst xs, map snd xs)
.
Querying either of the sequences returned by unzip xs
causes xs
to be queried. Therefore, querying both of them causes xs
to be queried twice. Thus, xs
must be persistent and cheap. If that is not the case, use unzip (memoize xs)
.
partition_map f xs
returns a pair of sequences (ys, zs)
, where:
ys
is the sequence of the elementsy
such thatf x = Left y
, wherex
ranges overxs
;
zs
is the sequence of the elementsz
such thatf x = Right z
, wherex
ranges overxs
.
partition_map f xs
is equivalent to a pair of filter_map Either.find_left (map f xs)
and filter_map Either.find_right (map f xs)
.
Querying either of the sequences returned by partition_map f xs
causes xs
to be queried. Therefore, querying both of them causes xs
to be queried twice. Thus, xs
must be persistent and cheap. If that is not the case, use partition_map f (memoize xs)
.
partition p xs
returns a pair of the subsequence of the elements of xs
that satisfy p
and the subsequence of the elements of xs
that do not satisfy p
.
partition p xs
is equivalent to filter p xs, filter (fun x -> not (p x)) xs
.
Consuming both of the sequences returned by partition p xs
causes xs
to be consumed twice and causes the function f
to be applied twice to each element of the list. Therefore, f
should be pure and cheap. Furthermore, xs
should be persistent and cheap. If that is not the case, use partition p (memoize xs)
.
Converting between sequences and dispensers
A dispenser is a representation of a sequence as a function of type unit -> 'a option
. Every time this function is invoked, it returns the next element of the sequence. When there are no more elements, it returns None
. A dispenser has mutable internal state, therefore is ephemeral: the sequence that it represents can be consumed at most once.
of_dispenser it
is the sequence of the elements produced by the dispenser it
. It is an ephemeral sequence: it can be consumed at most once. If a persistent sequence is needed, use memoize (of_dispenser it)
.
to_dispenser xs
is a fresh dispenser on the sequence xs
.
This dispenser has mutable internal state, which is not protected by a lock; so, it must not be used by several threads concurrently.
Sequences of integers
ints i
is the infinite sequence of the integers beginning at i
and counting up.