add CCVec; deprecate CCVector

get rid of the permission stuff; improve API a bit
This commit is contained in:
Simon Cruanes 2023-06-06 12:00:41 -04:00
parent 94e9335c35
commit 203e378cea
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
3 changed files with 1063 additions and 1 deletions

690
src/core/CCVec.ml Normal file
View file

@ -0,0 +1,690 @@
(* This file is free software, part of containers. See file "license" for more details. *)
type 'a iter = ('a -> unit) -> unit
type 'a equal = 'a -> 'a -> bool
type 'a ord = 'a -> 'a -> int
type 'a printer = Format.formatter -> 'a -> unit
type 'a t = { mutable size: int; mutable vec: 'a array }
(** A vector of 'a. *)
external as_float_arr : 'a array -> float array = "%identity"
external as_obj_arr : 'a array -> Obj.t array = "%identity"
let fill_with_junk_ (a : _ array) i len : unit =
if Obj.(tag (repr a) = double_array_tag) then
Array.fill (as_float_arr a) i len 0.
else
Array.fill (as_obj_arr a) i len (Obj.repr ())
let freeze v = { size = v.size; vec = v.vec }
let freeze_copy v = { size = v.size; vec = Array.sub v.vec 0 v.size }
let create () = { size = 0; vec = [||] }
let create_with ?(capacity = 128) x =
let vec = Array.make capacity x in
fill_with_junk_ vec 0 capacity;
{ size = 0; vec }
let return x = { size = 1; vec = [| x |] }
let make n x = { size = n; vec = Array.make n x }
let init n f = { size = n; vec = Array.init n f }
(* is the underlying array empty? *)
let[@inline] array_is_empty_ v = Array.length v.vec = 0
(* next capacity, if current one is [n] *)
let[@inline] next_grow_ n = min Sys.max_array_length (n + (n lsr 1) + 2)
(* resize the underlying array using x to temporarily fill the array *)
let resize_ v newcapacity x =
assert (newcapacity >= v.size);
assert (not (array_is_empty_ v));
let new_vec = Array.make newcapacity x in
Array.blit v.vec 0 new_vec 0 v.size;
fill_with_junk_ new_vec v.size (newcapacity - v.size);
v.vec <- new_vec;
()
(* grow the array, using [x] as a filler if required *)
let grow_with_ v ~filler:x =
if array_is_empty_ v then (
let len = 4 in
v.vec <- Array.make len x;
(* do not really use [x], it was just for knowing the type *)
fill_with_junk_ v.vec 0 len
) else (
let n = Array.length v.vec in
let size = next_grow_ n in
if size = n then invalid_arg "vec: can't grow any further";
resize_ v size v.vec.(0)
)
(* v is not empty; ensure it has at least [size] slots.
Use a doubling-size strategy so that calling many times [ensure] will
behave well *)
let ensure_assuming_not_empty_ v ~size =
if size > Sys.max_array_length then
invalid_arg "vec.ensure: size too big"
else if size < Array.length v.vec then
()
(* nothing to do *)
else (
let n = ref (Array.length v.vec) in
while !n < size do
n := next_grow_ !n
done;
resize_ v !n v.vec.(0)
)
let ensure_with ~init v size =
if array_is_empty_ v then (
v.vec <- Array.make size init;
fill_with_junk_ v.vec 0 size
) else
ensure_assuming_not_empty_ v ~size
let ensure v size =
if not (array_is_empty_ v) then ensure_assuming_not_empty_ v ~size
let[@inline] clear v = v.size <- 0
let clear_and_reset v =
v.size <- 0;
v.vec <- [||]
(* TODO*)
(*
let v = create() in
let a = Weak.create 1 in
push v ("hello"^"world");
Weak.set a 0 (Some (get v 0));
Gc.full_major(); Gc.compact();
assert_bool "is alive" (Weak.check a 0);
Gc.full_major(); Gc.compact();
assert_equal None (Weak.get a 0);
*)
let[@inline] is_empty v = v.size = 0
let[@inline] push_unsafe_ v x =
Array.unsafe_set v.vec v.size x;
v.size <- v.size + 1
let push v x =
if v.size = Array.length v.vec then grow_with_ v ~filler:x;
push_unsafe_ v x
let resize_with v f size =
if size < 0 then invalid_arg "Vec.resize_with";
if Array.length v.vec = 0 then (
let new_vec = Array.init size f in
v.vec <- new_vec;
v.size <- size
) else (
ensure_assuming_not_empty_ v size;
let { size = cur_size; vec } = v in
for i = cur_size to size - 1 do
Array.unsafe_set vec i (f i)
done;
assert (size <= Array.length v.vec);
v.size <- size
)
let resize_with_init v ~init size =
if size < 0 then invalid_arg "Vec.resize_with_init";
if Array.length v.vec = 0 then (
let vec = Array.make size init in
v.vec <- vec;
v.size <- size
) else (
ensure_assuming_not_empty_ v size;
(* nothing will change [v] *)
for i = v.size to size - 1 do
Array.unsafe_set v.vec i init
done;
v.size <- size
)
(** Add all elements of b to a *)
let append a b =
if array_is_empty_ a then
if array_is_empty_ b then
()
else (
a.vec <- Array.copy b.vec;
a.size <- b.size
)
else (
ensure_assuming_not_empty_ a ~size:(a.size + b.size);
assert (Array.length a.vec >= a.size + b.size);
Array.blit b.vec 0 a.vec a.size b.size;
a.size <- a.size + b.size
)
let[@inline] get v i =
if i < 0 || i >= v.size then invalid_arg "CCVector.get";
Array.unsafe_get v.vec i
let[@inline] set v i x =
if i < 0 || i >= v.size then invalid_arg "CCVector.set";
Array.unsafe_set v.vec i x
let remove_and_shift v i =
if i < 0 || i >= v.size then invalid_arg "CCVector.remove";
(* if v.(i) not the last element, then put last element at index i *)
if i < v.size - 1 then Array.blit v.vec (i + 1) v.vec i (v.size - i - 1);
(* remove one element *)
v.size <- v.size - 1;
fill_with_junk_ v.vec v.size 1
let remove_unordered v i =
if i < 0 || i >= v.size then invalid_arg "CCVector.remove_unordered";
(* if v.(i) not the last element, then put last element at index i *)
if i < v.size - 1 then v.vec.(i) <- v.vec.(v.size - 1);
(* remove one element *)
v.size <- v.size - 1;
fill_with_junk_ v.vec v.size 1
let insert v i x =
(* Note that we can insert at i=v.size *)
if i < 0 || i > v.size then invalid_arg "CCVector.insert";
if v.size = Array.length v.vec then grow_with_ v ~filler:x;
(* Shift the following elements, then put the element at i *)
if i < v.size then Array.blit v.vec i v.vec (i + 1) (v.size - i);
v.vec.(i) <- x;
v.size <- v.size + 1
let[@inline] append_iter a i = i (fun x -> push a x)
let append_seq a seq = Seq.iter (fun x -> push a x) seq
let append_array a b =
let len_b = Array.length b in
if array_is_empty_ a then (
a.vec <- Array.copy b;
a.size <- len_b
) else (
ensure_assuming_not_empty_ a ~size:(a.size + len_b);
Array.blit b 0 a.vec a.size len_b;
a.size <- a.size + len_b
)
let append_list a b =
match b with
| [] -> ()
| x :: _ ->
(* need to push at least one elem *)
let len_a = a.size in
let len_b = List.length b in
ensure_with ~init:x a (len_a + len_b);
List.iter (push_unsafe_ a) b;
()
let rec append_gen a b =
match b () with
| None -> ()
| Some x ->
push a x;
append_gen a b
let equal eq v1 v2 =
v1.size = v2.size
&&
let n = v1.size in
let rec check i = i = n || (eq (get v1 i) (get v2 i) && check (i + 1)) in
check 0
let compare cmp v1 v2 =
let n = min v1.size v2.size in
let rec check i =
if i = n then
compare v1.size v2.size
else (
let c = cmp (get v1 i) (get v2 i) in
if c = 0 then
check (i + 1)
else
c
)
in
check 0
exception Empty
let pop_exn v =
if v.size = 0 then raise Empty;
let new_size = v.size - 1 in
v.size <- new_size;
let x = v.vec.(new_size) in
(* free last element *)
fill_with_junk_ v.vec new_size 1;
x
let pop v = try Some (pop_exn v) with Empty -> None
let[@inline] top v =
if v.size = 0 then
None
else
Some (Array.unsafe_get v.vec (v.size - 1))
let[@inline] top_exn v =
if v.size = 0 then raise Empty;
Array.unsafe_get v.vec (v.size - 1)
let[@inline] copy v = { size = v.size; vec = Array.sub v.vec 0 v.size }
let truncate v n =
let old_size = v.size in
if n < old_size then (
v.size <- n;
(* free elements by erasing them *)
fill_with_junk_ v.vec n (old_size - n)
)
let shrink_to_fit v : unit =
if v.size = 0 then
v.vec <- [||]
else if v.size < Array.length v.vec then
v.vec <- Array.sub v.vec 0 v.size
let sort cmp v =
(* possibly copy array (to avoid junk at its end), then sort the array *)
let a =
if Array.length v.vec = v.size then
v.vec
else
Array.sub v.vec 0 v.size
in
Array.fast_sort cmp a;
v.vec <- a
let sorted cmp v =
let v' = { size = v.size; vec = Array.sub v.vec 0 v.size } in
Array.sort cmp v'.vec;
v'
let uniq_sort cmp v =
sort cmp v;
let n = v.size in
(* traverse to remove duplicates. i= current index,
j=current append index, j<=i. new_size is the size
the vector will have after removing duplicates. *)
let rec traverse prev i j =
if i >= n then
()
(* done traversing *)
else if cmp prev v.vec.(i) = 0 then (
v.size <- v.size - 1;
traverse prev (i + 1) j (* duplicate, remove it *)
) else (
v.vec.(j) <- v.vec.(i);
traverse v.vec.(i) (i + 1) (j + 1)
)
(* keep it *)
in
if v.size > 0 then traverse v.vec.(0) 1 1
(* start at 1, to get the first element in hand *)
let iter k v =
let { vec; size = n } = v in
for i = 0 to n - 1 do
k (Array.unsafe_get vec i)
done
let iteri k v =
let { vec; size = n } = v in
for i = 0 to n - 1 do
k i (Array.unsafe_get vec i)
done
let map f v =
if array_is_empty_ v then
create ()
else (
let { vec; size } = v in
let vec = Array.init size (fun i -> f (Array.unsafe_get vec i)) in
{ size; vec }
)
let mapi f v =
if array_is_empty_ v then
create ()
else (
let { vec; size } = v in
let vec = Array.init size (fun i -> f i (Array.unsafe_get vec i)) in
{ size; vec }
)
let map_in_place f v =
let { vec; size = n } = v in
for i = 0 to n - 1 do
Array.unsafe_set vec i (f (Array.unsafe_get vec i))
done
let filter_in_place p v =
let i = ref 0 in
(* cur element *)
let j = ref 0 in
(* cur insertion point *)
let n = v.size in
while !i < n do
if p v.vec.(!i) then (
(* move element i at the first empty slot.
invariant: i >= j*)
if !i > !j then v.vec.(!j) <- v.vec.(!i);
incr i;
incr j
) else
incr i
done;
(* free elements *)
fill_with_junk_ v.vec !j (v.size - !j);
v.size <- !j
let filter p v =
if array_is_empty_ v then
create ()
else (
let v' = create_with ~capacity:v.size v.vec.(0) in
iter (fun x -> if p x then push_unsafe_ v' x) v;
v'
)
let fold_left f acc v =
let { vec; size } = v in
let rec fold acc i =
if i = size then
acc
else (
let x = Array.unsafe_get vec i in
fold (f acc x) (i + 1)
)
in
fold acc 0
let fold = fold_left
let exists p v =
let n = v.size in
let rec check i =
if i = n then
false
else
p v.vec.(i) || check (i + 1)
in
check 0
let for_all p v =
let n = v.size in
let rec check i =
if i = n then
true
else
p v.vec.(i) && check (i + 1)
in
check 0
let member ~eq x v = exists (eq x) v
let find_internal_ p v =
let n = v.size in
let rec check i =
if i = n then
raise_notrace Not_found
else (
let x = v.vec.(i) in
if p x then
x
else
check (i + 1)
)
in
check 0
let find_exn p v = try find_internal_ p v with Not_found -> raise Not_found
let find p v = try Some (find_internal_ p v) with Not_found -> None
let find_map f v =
let n = v.size in
let rec search i =
if i = n then
None
else (
match f v.vec.(i) with
| None -> search (i + 1)
| Some _ as res -> res
)
in
search 0
let filter_map f v =
let v' = create () in
iter
(fun x ->
match f x with
| None -> ()
| Some y -> push v' y)
v;
v'
let filter_map_in_place f v =
let i = ref 0 in
(* cur element *)
let j = ref 0 in
(* cur insertion point *)
let n = v.size in
while !i < n do
match f v.vec.(!i) with
| None -> incr i (* drop *)
| Some y ->
(* move element i at the first empty slot.
invariant: i >= j*)
v.vec.(!j) <- y;
incr i;
incr j
done;
(* free elements *)
fill_with_junk_ v.vec !j (v.size - !j);
v.size <- !j
let flat_map f v =
let v' = create () in
iter (fun x -> iter (push v') (f x)) v;
v'
let flat_map_iter f v =
let v' = create () in
iter
(fun x ->
let seq = f x in
append_iter v' seq)
v;
v'
let flat_map_seq f v =
let v' = create () in
iter
(fun x ->
let seq = f x in
append_seq v' seq)
v;
v'
let flat_map_list f v =
let v' = create () in
iter
(fun x ->
let l = f x in
append_list v' l)
v;
v'
let cartesian_product f a1 a2 : _ t =
let na1 = a1.size in
init (na1 * a2.size) (fun i_prod ->
let i = i_prod mod na1 in
let j = i_prod / na1 in
f a1.vec.(i) a2.vec.(j))
let rev_in_place v =
if v.size > 0 then (
let n = v.size in
let vec = v.vec in
for i = 0 to (n - 1) / 2 do
let x = Array.unsafe_get vec i in
let y = Array.unsafe_get vec (n - i - 1) in
Array.unsafe_set vec i y;
Array.unsafe_set vec (n - i - 1) x
done
)
let rev v =
let v' = copy v in
rev_in_place v';
v'
let rev_iter f v =
let { vec; size = n } = v in
for i = n - 1 downto 0 do
f (Array.unsafe_get vec i)
done
let size v = v.size
let length v = v.size
let capacity v = Array.length v.vec
let unsafe_get_array v = v.vec
let of_iter ?(init = create ()) seq =
append_iter init seq;
init
let of_seq ?(init = create ()) seq =
append_seq init seq;
init
let to_iter v k = iter k v
let to_iter_rev v k =
let { vec; size = n } = v in
for i = n - 1 downto 0 do
k (Array.unsafe_get vec i)
done
let to_seq v =
let { size; vec } = v in
let rec aux i () =
if i >= size then
Seq.Nil
else
Seq.Cons (vec.(i), aux (i + 1))
in
aux 0
let to_seq_rev v =
let { size; vec } = v in
let rec aux i () =
if i < 0 then
Seq.Nil
else
Seq.Cons (vec.(i), aux (i - 1))
in
aux (size - 1)
let slice_iter v start len =
assert (start >= 0 && len >= 0);
fun k ->
let { size; vec } = v in
assert (start + len <= size);
for i = start to start + len - 1 do
let x = Array.unsafe_get vec i in
k x
done
let range_inclusive i j =
if i > j then
init (i - j + 1) (fun k -> i - k)
else
init (j - i + 1) (fun k -> i + k)
let range_exclusive i j =
if i = j then
create ()
else if i > j then
init (i - j) (fun k -> i - k)
else
init (j - i) (fun k -> i + k)
let unsafe_slice v = v.vec, 0, v.size
let of_array a =
if Array.length a = 0 then
create ()
else
{ size = Array.length a; vec = Array.copy a }
let of_list l =
match l with
| [] -> create ()
| [ x ] -> return x
| [ x; y ] -> { size = 2; vec = [| x; y |] }
| x :: _ ->
let v = create_with ~capacity:(List.length l) x in
List.iter (push_unsafe_ v) l;
v
let to_array v = Array.sub v.vec 0 v.size
let to_list v = List.rev (fold (fun acc x -> x :: acc) [] v)
let of_gen ?(init = create ()) g =
let rec aux g =
match g () with
| None -> init
| Some x ->
push init x;
aux g
in
aux g
let to_gen v =
let { size; vec } = v in
let i = ref 0 in
fun () ->
if !i < size then (
let x = vec.(!i) in
incr i;
Some x
) else
None
let to_string ?(start = "") ?(stop = "") ?(sep = ", ") item_to_string v =
start ^ (to_list v |> List.map item_to_string |> String.concat sep) ^ stop
let pp ?(pp_start = fun _ () -> ()) ?(pp_stop = fun _ () -> ())
?(pp_sep = fun fmt () -> Format.fprintf fmt ",@ ") pp_item fmt v =
pp_start fmt ();
iteri
(fun i x ->
if i > 0 then pp_sep fmt ();
pp_item fmt x)
v;
pp_stop fmt ()
module Infix = struct
let ( -- ) = range_inclusive
let ( --^ ) = range_exclusive
let ( >>= ) x f = flat_map f x
let ( >|= ) x f = map f x
[@@@ifge 4.8]
let ( let+ ) = ( >|= )
let ( let* ) = ( >>= )
let[@inline] ( and+ ) a1 a2 = cartesian_product (fun x y -> x, y) a1 a2
let ( and* ) = ( and+ )
[@@@endif]
end
include Infix

367
src/core/CCVec.mli Normal file
View file

@ -0,0 +1,367 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** Growable, mutable vector.
This replaces {!CCVector}, removing permissions, and re-vamping the API overall.
@since NEXT_RELEASE
*)
type 'a t
(** The type of a vector of elements of type ['a], with *)
type 'a iter = ('a -> unit) -> unit
(** Fast internal iterator. *)
type 'a equal = 'a -> 'a -> bool
type 'a ord = 'a -> 'a -> int
type 'a printer = Format.formatter -> 'a -> unit
val create : unit -> 'a t
(** Create a new, empty vector. *)
val create_with : ?capacity:int -> 'a -> 'a t
(** Create a new vector, the value is used to enforce the type the new vector.
@param capacity the size of the underlying array. *)
val return : 'a -> 'a t
(** Singleton vector.
@since 0.14 *)
val make : int -> 'a -> 'a t
(** [make n x] makes a vector of size [n], filled with [x]. *)
val init : int -> (int -> 'a) -> 'a t
(** Init the vector with the given function and size. *)
val clear : _ t -> unit
(** Clear the content of the vector.
This ensures that [length v = 0] but the underlying array is kept,
and possibly references to former elements, which are therefore
not garbage collectible. *)
val clear_and_reset : _ t -> unit
(** Clear the content of the vector, and deallocate the underlying array,
removing references to all the elements. The elements can be collected. *)
val ensure_with : init:'a -> 'a t -> int -> unit
(** Hint to the vector that it should have at least the given capacity.
This does not affect [length v].
@param init if [capacity v = 0], used to enforce the type of the vector
(see {!create_with}).
@raise Invalid_arg if the size is not suitable (negative, or too big for OCaml arrays) *)
val ensure : _ t -> int -> unit
(** Hint to the vector that it should have at least the given capacity.
Just a hint, will not be enforced if the vector is empty and [init]
is not provided.
@raise Invalid_arg if the size is not suitable (negative, or too big for OCaml arrays)
*)
val is_empty : _ t -> bool
(** Is the vector empty? *)
val push : 'a t -> 'a -> unit
(** Add an element at the end of the vector. *)
val resize_with : 'a t -> (int -> 'a) -> int -> unit
(** [resize_with vec f size] resizes vector [vec] up to [size], fills vector
with calls to [f] on indexes [[vec.size-1.. size - 1]].
The contents and size of vec are untouched if [size] is inferior or equal
to [length vec].
@raise Invalid_argument if the size is too big *)
val resize_with_init : 'a t -> init:'a -> int -> unit
(** [resize_with_init vec init size] resizes vector [vec] up to [size],
fills vector with calls to [init] on indexes [[length vec -1.. size - 1]].
The contents and size of vec are untouched if [size] is inferior or equal
to [length vec].
@raise Invalid_argument if the size is too big *)
val append : 'a t -> 'a t -> unit
(** [append a b] adds all elements of [b] to [a]. *)
val append_array : 'a t -> 'a array -> unit
(** Like {!append}, with an array. *)
val append_iter : 'a t -> 'a iter -> unit
(** Append content of iterator. *)
val append_seq : 'a t -> 'a Seq.t -> unit
(** Append content of iterator.
Renamed from [append_std_seq] since 3.0. *)
val append_list : 'a t -> 'a list -> unit
(** Append content of list. *)
val equal : 'a equal -> 'a t equal
(** Content-wise equality *)
val compare : 'a ord -> 'a t ord
(** Total ordering on vectors. Lexicographic comparison. *)
exception Empty
(** Raised on empty stack/vector. *)
val pop : 'a t -> 'a option
(** Remove last element, or [None]. *)
val pop_exn : 'a t -> 'a
(** Remove last element, or raise an exception if empty.
@raise Empty on an empty vector. *)
val top : 'a t -> 'a option
(** Top element, if present. *)
val top_exn : 'a t -> 'a
(** Top element, if present.
@raise Empty on an empty vector. *)
val copy : 'a t -> 'a t
(** Shallow copy. *)
val truncate : _ t -> int -> unit
(** Truncate to the given size (remove elements above this size).
Does nothing if the parameter is bigger than the current size. *)
val shrink_to_fit : _ t -> unit
(** Shrink internal array to fit the size of the vector. This will
most likely reallocate the internal array. *)
val member : ('a -> 'a -> bool) -> 'a -> 'a t -> bool
(** Is the element a member of the vector? *)
val sorted : ('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the vector, returning a copy of it that is sorted
w.r.t the given ordering. The vector itself is unchanged.
The underlying array of the new vector can be smaller than
the original one. *)
val sort : ('a -> 'a -> int) -> 'a t -> unit
(** Sort the vector in place (modifying it).
This function change the size of the underlying array. *)
val uniq_sort : ('a -> 'a -> int) -> 'a t -> unit
(** Sort the array and remove duplicates, in place (e.g. modifying
the vector itself). *)
val iter : ('a -> unit) -> 'a t -> unit
(** Iterate on the vector's content. *)
val iteri : (int -> 'a -> unit) -> 'a t -> unit
(** Iterate on the vector, with indexes. *)
val map : ('a -> 'b) -> 'a t -> 'b t
(** Map elements of the vector, yielding a new vector. *)
val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t
(** [map f v] is just like {!map}, but it also passes in the index
of each element as the first argument to the function [f]. *)
val map_in_place : ('a -> 'a) -> 'a t -> unit
(** Map elements of the vector in place. *)
val filter : ('a -> bool) -> 'a t -> 'a t
(** Filter elements from the vector. [filter p v] leaves [v] unchanged but
returns a new vector that only contains elements of [v] satisfying [p]. *)
val filter_in_place : ('a -> bool) -> 'a t -> unit
(** Filter elements from the vector in place. *)
val fold_left : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
(** Fold on elements of the vector *)
val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
(** Fold on elements of the vector. Alias for {!fold_left}. *)
val exists : ('a -> bool) -> 'a t -> bool
(** Existential test (is there an element that satisfies the predicate?). *)
val for_all : ('a -> bool) -> 'a t -> bool
(** Universal test (do all the elements satisfy the predicate?). *)
val find : ('a -> bool) -> 'a t -> 'a option
(** Find an element that satisfies the predicate. *)
val find_exn : ('a -> bool) -> 'a t -> 'a
(** Find an element that satisfies the predicate, or
@raise Not_found if no element does. *)
val find_map : ('a -> 'b option) -> 'a t -> 'b option
(** [find_map f v] returns the first [Some y = f x] for [x] in [v],
or [None] if [f x = None] for each [x] in [v]. *)
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
(** Map elements with a function, possibly filtering some of them out. *)
val filter_map_in_place : ('a -> 'a option) -> 'a t -> unit
(** Filter-map elements of the vector in place. *)
val flat_map : ('a -> 'b t) -> 'a t -> 'b t
(** Map each element to a sub-vector. *)
val flat_map_seq : ('a -> 'b Seq.t) -> 'a t -> 'b t
(** Like {!flat_map}, but using [Seq] for intermediate collections. *)
val flat_map_list : ('a -> 'b list) -> 'a t -> 'b t
(** Like {!flat_map}, but using {!list} for
intermediate collections. *)
val cartesian_product : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** All combinaisons of tuples from the two vectors are passed to the function. *)
val range_inclusive : int -> int -> int t
(** Range of integers, either ascending or descending, where both
bounds are included, therefore the result is never empty).
Example: [1 -- 10] returns the vector [[1;2;3;4;5;6;7;8;9;10]]. *)
val range_exclusive : int -> int -> int t
(** Range of integers, either ascending or descending, but excluding the second argument.
Example: [1 --^ 10] returns the vector [[1;2;3;4;5;6;7;8;9]]. *)
module Infix : sig
val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t
(** Infix version of {!flat_map}. *)
val ( >|= ) : 'a t -> ('a -> 'b) -> 'b t
(** Infix version of {!map}. *)
val ( -- ) : int -> int -> int t
(** Alias for {!range_inclusive} *)
val ( --^ ) : int -> int -> int t
(** Alias for {!range_exclusive} *)
[@@@ifge 4.08]
val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t
(** @since 2.8 *)
val ( and+ ) : 'a t -> 'b t -> ('a * 'b) t
(** @since 2.8 *)
val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t
(** @since 2.8 *)
val ( and* ) : 'a t -> 'b t -> ('a * 'b) t
(** @since 2.8 *)
[@@@endif]
end
include module type of Infix
val get : 'a t -> int -> 'a
(** Access element by its index, or
@raise Invalid_argument if bad index. *)
val set : 'a t -> int -> 'a -> unit
(** Modify element at given index, or
@raise Invalid_argument if the index is
invalid (i.e. not in [[0.. length v-1]]). *)
val remove_and_shift : 'a t -> int -> unit
(** [remove_and_shift v i] remove the [i-th] element from [v].
Move elements that are after the [i-th] in [v], in linear time.
Preserve the order of the elements in [v].
See {!remove_unordered} for constant time removal function that doesn't
preserve the order of elements. *)
val remove_unordered : 'a t -> int -> unit
(** [remove_unordered v i] remove the [i-th] element from [v].
Does {b NOT} preserve the order of the elements in [v]
(might swap with the last element).
See {!remove_and_shift} if you want to keep the ordering. *)
val insert : 'a t -> int -> 'a -> unit
(** [insert v i x] insert the given element at index i.
Elements at location [i] and later are first shifted over in linear time before inserting [x].
Preserve the order of elements in [v]. *)
val rev : 'a t -> 'a t
(** Reverse the vector. *)
val rev_in_place : 'a t -> unit
(** Reverse the vector in place. *)
val rev_iter : ('a -> unit) -> 'a t -> unit
(** [rev_iter f a] is the same as [iter f (rev a)], only more efficient. *)
val size : _ t -> int
(** Number of elements in the vector. *)
val length : _ t -> int
(** Synonym for {! size}. *)
val capacity : _ t -> int
(** Number of elements the vector can contain without being resized. *)
val unsafe_get_array : 'a t -> 'a array
(** Access the underlying {b shared} array (do not modify!).
[unsafe_get_array v] is longer than [size v], but elements at higher
index than [size v] are undefined (do not access!). *)
val of_array : 'a array -> 'a t
(** [of_array a] returns a vector corresponding to the array [a]. Operates in [O(n)] time. *)
val of_list : 'a list -> 'a t
val to_array : 'a t -> 'a array
(** [to_array v] returns an array corresponding to the vector [v].
This allocates a new array. *)
val to_list : 'a t -> 'a list
(** Return a list with the elements contained in the vector. *)
val of_iter : ?init:'a t -> 'a iter -> 'a t
(** Convert an Iterator to a vector. *)
val of_seq : ?init:'a t -> 'a Seq.t -> 'a t
(** Convert an Iterator to a vector. *)
val to_iter : 'a t -> 'a iter
(** Return a [iter] with the elements contained in the vector. *)
val to_iter_rev : 'a t -> 'a iter
(** [to_iter_rev v] returns the sequence of elements of [v] in reverse order,
that is, the last elements of [v] are iterated on first.
*)
val to_seq : 'a t -> 'a Seq.t
(** Return an iterator with the elements contained in the vector.
Renamed from [to_std_seq] since 3.0.
*)
val to_seq_rev : 'a t -> 'a Seq.t
(** [to_seq v] returns the sequence of elements of [v] in reverse order,
that is, the last elements of [v] are iterated on first.
*)
val unsafe_slice : 'a t -> 'a array * int * int
(** Vector as an array slice. By doing it we expose the internal array, so
be careful!. *)
val slice_iter : 'a t -> int -> int -> 'a iter
(** [slice_iter v start len] is the sequence of elements from [v.(start)]
to [v.(start+len-1)].
*)
val to_string :
?start:string ->
?stop:string ->
?sep:string ->
('a -> string) ->
'a t ->
string
(** Print the vector in a string. *)
val pp :
?pp_start:unit printer ->
?pp_stop:unit printer ->
?pp_sep:unit printer ->
'a printer ->
'a t printer
(** [pp ~pp_start ~pp_stop ~pp_sep pp_item ppf v] formats the vector [v] on [ppf].
Each element is formatted with [pp_item], [pp_start] is called at the beginning,
[pp_stop] is called at the end, [pp_sep] is called between each elements.
By defaults [pp_start] and [pp_stop] does nothing and [pp_sep] defaults to
(fun out -> Format.fprintf out ",@ "). *)

View file

@ -1,6 +1,11 @@
(* This file is free software, part of containers. See file "license" for more details. *) (* This file is free software, part of containers. See file "license" for more details. *)
(** Growable, mutable vector *) (** Growable, mutable vector
@deprecated since NEXT_RELEASE , see {!CCVec} instead *)
[@@@deprecated "use CCVec"]
type ro = [ `RO ] type ro = [ `RO ]
type rw = [ `RW ] type rw = [ `RW ]