use Labels versions of CCList and CCArray

This commit is contained in:
Simon Cruanes 2016-12-29 11:07:44 +01:00
parent a8babbd941
commit 9b53e3c2a5
13 changed files with 884 additions and 213 deletions

View file

@ -62,7 +62,7 @@ push_doc_gh: doc
cp -r containers.docdir/* dev/ && \ cp -r containers.docdir/* dev/ && \
git add --all dev git add --all dev
DONTTEST=myocamlbuild.ml setup.ml $(wildcard src/**/*.cppo.*) DONTTEST=myocamlbuild.ml setup.ml $(wildcard src/**/*.cppo.*) $(wildcard src/**/*Labels*)
QTESTABLE=$(filter-out $(DONTTEST), \ QTESTABLE=$(filter-out $(DONTTEST), \
$(wildcard src/core/*.ml) \ $(wildcard src/core/*.ml) \
$(wildcard src/core/*.mli) \ $(wildcard src/core/*.mli) \

1
_oasis
View file

@ -35,6 +35,7 @@ Library "containers"
CCFun, CCHash, CCInt, CCBool, CCFloat, CCArray, CCRef, CCSet, CCFun, CCHash, CCInt, CCBool, CCFloat, CCArray, CCRef, CCSet,
CCOrd, CCRandom, CCString, CCHashtbl, CCMap, CCFormat, CCIO, CCOrd, CCRandom, CCString, CCHashtbl, CCMap, CCFormat, CCIO,
CCInt64, CCChar, CCResult, CCParse, CCArray_slice, CCInt64, CCChar, CCResult, CCParse, CCArray_slice,
CCListLabels, CCArrayLabels,
Containers Containers
BuildDepends: bytes, result BuildDepends: bytes, result
# BuildDepends: bytes, bisect_ppx # BuildDepends: bytes, bisect_ppx

1
_tags
View file

@ -159,3 +159,4 @@ true: annot, bin_annot
<src/data/CCFlatHashtbl.cm*> or <src/data/CCHashTrie.cm*> or <src/data/CCPersistent*>: inline(15) <src/data/CCFlatHashtbl.cm*> or <src/data/CCHashTrie.cm*> or <src/data/CCPersistent*>: inline(15)
<src/**/*.ml> and not <src/misc/*.ml>: warn_A, warn(-4), warn(-44) <src/**/*.ml> and not <src/misc/*.ml>: warn_A, warn(-4), warn(-44)
true: no_alias_deps, safe_string, short_paths true: no_alias_deps, safe_string, short_paths
<src/**/*Labels.cm*>: nolabels

View file

@ -22,9 +22,9 @@ type 'a t = 'a array
let empty = [| |] let empty = [| |]
let map ~f a = Array.map f a let map = Array.map
let map2 ~f a b = let map2 f a b =
if Array.length a <> Array.length b then invalid_arg "map2"; if Array.length a <> Array.length b then invalid_arg "map2";
Array.init (Array.length a) (fun i -> f (Array.unsafe_get a i) (Array.unsafe_get b i)) Array.init (Array.length a) (fun i -> f (Array.unsafe_get a i) (Array.unsafe_get b i))
@ -49,15 +49,15 @@ let get_safe a i =
let set = Array.set let set = Array.set
let fold ~f ~init a = Array.fold_left f init a let fold = Array.fold_left
let foldi ~f ~init a = let foldi f acc a =
let rec aux acc i = let rec aux acc i =
if i = Array.length a then acc else aux (f acc i a.(i)) (i+1) if i = Array.length a then acc else aux (f acc i a.(i)) (i+1)
in in
aux init 0 aux acc 0
let fold_while ~f ~init a = let fold_while f acc a =
let rec fold_while_i f acc i = let rec fold_while_i f acc i =
if i < Array.length a then if i < Array.length a then
let acc, cont = f acc a.(i) in let acc, cont = f acc a.(i) in
@ -65,16 +65,15 @@ let fold_while ~f ~init a =
| `Stop -> acc | `Stop -> acc
| `Continue -> fold_while_i f acc (i+1) | `Continue -> fold_while_i f acc (i+1)
else acc else acc
in fold_while_i f init 0 in fold_while_i f acc 0
(*$T (*$T
fold_while ~f:(fun acc b -> if b then acc+1, `Continue else acc, `Stop) \ fold_while (fun acc b -> if b then acc+1, `Continue else acc, `Stop) 0 (Array.of_list [true;true;false;true]) = 2
~init:0 (Array.of_list [true;true;false;true]) = 2
*) *)
let iter ~f a = Array.iter f a let iter = Array.iter
let iteri ~f a = Array.iteri f a let iteri = Array.iteri
let blit = Array.blit let blit = Array.blit
@ -99,53 +98,53 @@ let reverse_in_place a =
a = [| 6;5;4;3;2;1 |] a = [| 6;5;4;3;2;1 |]
*) *)
let sorted ~f a = let sorted cmp a =
let b = Array.copy a in let b = Array.copy a in
Array.sort f b; Array.sort cmp b;
b b
(*$= & ~cmp:(=) ~printer:Q.Print.(array int) (*$= & ~cmp:(=) ~printer:Q.Print.(array int)
[||] (sorted ~f:Pervasives.compare [||]) [||] (sorted Pervasives.compare [||])
[|0;1;2;3;4|] (sorted ~f:Pervasives.compare [|3;2;1;4;0|]) [|0;1;2;3;4|] (sorted Pervasives.compare [|3;2;1;4;0|])
*) *)
(*$Q (*$Q
Q.(array int) (fun a -> \ Q.(array int) (fun a -> \
let b = Array.copy a in \ let b = Array.copy a in \
Array.sort Pervasives.compare b; b = sorted ~f:Pervasives.compare a) Array.sort Pervasives.compare b; b = sorted Pervasives.compare a)
*) *)
let sort_indices ~f:cmp a = let sort_indices cmp a =
let len = Array.length a in let len = Array.length a in
let b = Array.init len (fun k->k) in let b = Array.init len (fun k->k) in
Array.sort (fun k1 k2 -> cmp a.(k1) a.(k2)) b; Array.sort (fun k1 k2 -> cmp a.(k1) a.(k2)) b;
b b
(*$= & ~cmp:(=) ~printer:Q.Print.(array int) (*$= & ~cmp:(=) ~printer:Q.Print.(array int)
[||] (sort_indices ~f:Pervasives.compare [||]) [||] (sort_indices Pervasives.compare [||])
[|4;2;1;0;3|] (sort_indices ~f:Pervasives.compare [|"d";"c";"b";"e";"a"|]) [|4;2;1;0;3|] (sort_indices Pervasives.compare [|"d";"c";"b";"e";"a"|])
*) *)
(*$Q (*$Q
Q.(array printable_string) (fun a -> \ Q.(array printable_string) (fun a -> \
let b = sort_indices ~f:String.compare a in \ let b = sort_indices String.compare a in \
sorted ~f:String.compare a = map ~f:(Array.get a) b) sorted String.compare a = Array.map (Array.get a) b)
*) *)
let sort_ranking ~f:cmp a = let sort_ranking cmp a =
let cmp_int : int -> int -> int = Pervasives.compare in let cmp_int : int -> int -> int = Pervasives.compare in
sort_indices ~f:cmp_int (sort_indices ~f:cmp a) sort_indices cmp_int (sort_indices cmp a)
(*$= & ~cmp:(=) ~printer:Q.Print.(array int) (*$= & ~cmp:(=) ~printer:Q.Print.(array int)
[||] (sort_ranking ~f:Pervasives.compare [||]) [||] (sort_ranking Pervasives.compare [||])
[|3;2;1;4;0|] (sort_ranking ~f:Pervasives.compare [|"d";"c";"b";"e";"a"|]) [|3;2;1;4;0|] (sort_ranking Pervasives.compare [|"d";"c";"b";"e";"a"|])
*) *)
(*$Q (*$Q
Q.(array printable_string) (fun a -> \ Q.(array printable_string) (fun a -> \
let b = sort_ranking ~f:String.compare a in \ let b = sort_ranking String.compare a in \
let a_sorted = sorted ~f:String.compare a in \ let a_sorted = sorted String.compare a in \
a = map ~f:(Array.get a_sorted) b) a = Array.map (Array.get a_sorted) b)
*) *)
let rev a = let rev a =
@ -169,16 +168,16 @@ let rec find_aux f a i =
| Some _ as res -> res | Some _ as res -> res
| None -> find_aux f a (i+1) | None -> find_aux f a (i+1)
let find ~f a = let find f a =
find_aux (fun _ -> f ) a 0 find_aux (fun _ -> f ) a 0
let findi ~f a = let findi f a =
find_aux f a 0 find_aux f a 0
let find_idx ~f a = let find_idx p a =
find_aux (fun i x -> if f x then Some (i,x) else None) a 0 find_aux (fun i x -> if p x then Some (i,x) else None) a 0
let filter_map ~f a = let filter_map f a =
let rec aux acc i = let rec aux acc i =
if i = Array.length a if i = Array.length a
then ( then (
@ -198,8 +197,8 @@ let filter_map ~f a =
= [| "2"; "4"; "6" |] = [| "2"; "4"; "6" |]
*) *)
let filter ~f a = let filter p a =
filter_map a ~f:(fun x -> if f x then Some x else None) filter_map (fun x -> if p x then Some x else None) a
(* append [rev a] in front of [acc] *) (* append [rev a] in front of [acc] *)
let rec __rev_append_list a acc i = let rec __rev_append_list a acc i =
@ -208,7 +207,7 @@ let rec __rev_append_list a acc i =
else else
__rev_append_list a (a.(i) :: acc) (i+1) __rev_append_list a (a.(i) :: acc) (i+1)
let flat_map ~f a = let flat_map f a =
let rec aux acc i = let rec aux acc i =
if i = Array.length a if i = Array.length a
then ( then (
@ -252,11 +251,11 @@ let _lookup_exn ~cmp k a i j =
| n when n<0 -> _lookup_rec ~cmp k a (i+1) (j-1) | n when n<0 -> _lookup_rec ~cmp k a (i+1) (j-1)
| _ -> raise Not_found (* too high *) | _ -> raise Not_found (* too high *)
let lookup_exn ?(cmp=Pervasives.compare) ~key a = let lookup_exn ?(cmp=Pervasives.compare) k a =
_lookup_exn ~cmp key a 0 (Array.length a-1) _lookup_exn ~cmp k a 0 (Array.length a-1)
let lookup ?(cmp=Pervasives.compare) ~key a = let lookup ?(cmp=Pervasives.compare) k a =
try Some (_lookup_exn ~cmp key a 0 (Array.length a-1)) try Some (_lookup_exn ~cmp k a 0 (Array.length a-1))
with Not_found -> None with Not_found -> None
(*$T (*$T
@ -269,20 +268,20 @@ let lookup ?(cmp=Pervasives.compare) ~key a =
lookup 2 [| 1 |] = None lookup 2 [| 1 |] = None
*) *)
let bsearch ?(cmp=Pervasives.compare) ~key a = let bsearch ?(cmp=Pervasives.compare) k a =
let rec aux i j = let rec aux i j =
if i > j if i > j
then `Just_after j then `Just_after j
else else
let middle = i + (j - i) / 2 in (* avoid overflow *) let middle = i + (j - i) / 2 in (* avoid overflow *)
match cmp key a.(middle) with match cmp k a.(middle) with
| 0 -> `At middle | 0 -> `At middle
| n when n<0 -> aux i (middle - 1) | n when n<0 -> aux i (middle - 1)
| _ -> aux (middle + 1) j | _ -> aux (middle + 1) j
in in
let n = Array.length a in let n = Array.length a in
if n=0 then `Empty if n=0 then `Empty
else match cmp a.(0) key, cmp a.(n-1) key with else match cmp a.(0) k, cmp a.(n-1) k with
| c, _ when c>0 -> `All_bigger | c, _ when c>0 -> `All_bigger
| _, c when c<0 -> `All_lower | _, c when c<0 -> `All_lower
| _ -> aux 0 (n-1) | _ -> aux 0 (n-1)
@ -297,37 +296,37 @@ let bsearch ?(cmp=Pervasives.compare) ~key a =
bsearch 3 [| |] = `Empty bsearch 3 [| |] = `Empty
*) *)
let (>>=) a f = flat_map ~f a let (>>=) a f = flat_map f a
let (>>|) a f = map ~f a let (>>|) a f = map f a
let (>|=) a f = map ~f a let (>|=) a f = map f a
let for_all ~f a = let for_all p a =
let rec aux i = let rec aux i =
i = Array.length a || (f a.(i) && aux (i+1)) i = Array.length a || (p a.(i) && aux (i+1))
in in
aux 0 aux 0
let exists ~f a = let exists p a =
let rec aux i = let rec aux i =
i <> Array.length a && (f a.(i) || aux (i+1)) i <> Array.length a && (p a.(i) || aux (i+1))
in in
aux 0 aux 0
let rec _for_all2 p a1 a2 i1 i2 ~len = let rec _for_all2 p a1 a2 i1 i2 ~len =
len=0 || (p a1.(i1) a2.(i2) && _for_all2 p a1 a2 (i1+1) (i2+1) ~len:(len-1)) len=0 || (p a1.(i1) a2.(i2) && _for_all2 p a1 a2 (i1+1) (i2+1) ~len:(len-1))
let for_all2 ~f a b = let for_all2 p a b =
Array.length a = Array.length b Array.length a = Array.length b
&& &&
_for_all2 f a b 0 0 ~len:(Array.length a) _for_all2 p a b 0 0 ~len:(Array.length a)
let rec _exists2 p a1 a2 i1 i2 ~len = let rec _exists2 p a1 a2 i1 i2 ~len =
len>0 && (p a1.(i1) a2.(i2) || _exists2 p a1 a2 (i1+1) (i2+1) ~len:(len-1)) len>0 && (p a1.(i1) a2.(i2) || _exists2 p a1 a2 (i1+1) (i2+1) ~len:(len-1))
let exists2 ~f a b = let exists2 p a b =
_exists2 f a b 0 0 ~len:(min (Array.length a) (Array.length b)) _exists2 p a b 0 0 ~len:(min (Array.length a) (Array.length b))
let _iter2 f a b i j ~len = let _iter2 f a b i j ~len =
for o = 0 to len-1 do for o = 0 to len-1 do
@ -343,13 +342,13 @@ let _fold2 f acc a b i j ~len =
in in
aux acc 0 aux acc 0
let iter2 ~f a b = let iter2 f a b =
if length a <> length b then invalid_arg "iter2"; if length a <> length b then invalid_arg "iter2";
_iter2 f a b 0 0 ~len:(Array.length a) _iter2 f a b 0 0 ~len:(Array.length a)
let fold2 ~f ~init a b = let fold2 f acc a b =
if length a <> length b then invalid_arg "fold2"; if length a <> length b then invalid_arg "fold2";
_fold2 f init a b 0 0 ~len:(Array.length a) _fold2 f acc a b 0 0 ~len:(Array.length a)
let (--) i j = let (--) i j =
if i<=j if i<=j
@ -382,9 +381,9 @@ let (--^) i j =
(** all the elements of a, but the i-th, into a list *) (** all the elements of a, but the i-th, into a list *)
let except_idx a i = let except_idx a i =
foldi a foldi
~f:(fun acc j elt -> if i = j then acc else elt::acc) (fun acc j elt -> if i = j then acc else elt::acc)
~init:[] [] a
let equal eq a b = let equal eq a b =
let rec aux i = let rec aux i =
@ -470,7 +469,7 @@ let pp_i ?(sep=", ") pp_item out a =
pp_item k out a.(k) pp_item k out a.(k)
done done
let to_seq a yield = iter ~f:yield a let to_seq a k = iter k a
let to_gen a = let to_gen a =
let k = ref 0 in let k = ref 0 in

View file

@ -31,19 +31,19 @@ val set : 'a t -> int -> 'a -> unit
val length : _ t -> int val length : _ t -> int
val fold : f:('a -> 'b -> 'a) -> init:'a -> 'b t -> 'a val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** Fold left on array, with index *) (** Fold left on array, with index *)
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
(** Fold left on array until a stop condition via [('a, `Stop)] is (** Fold left on array until a stop condition via [('a, `Stop)] is
indicated by the accumulator indicated by the accumulator
@since 0.8 *) @since 0.8 *)
val iter : f:('a -> unit) -> 'a t -> unit val iter : ('a -> unit) -> 'a t -> unit
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit val iteri : (int -> 'a -> unit) -> 'a t -> unit
val blit : 'a t -> int -> 'a t -> int -> int -> unit val blit : 'a t -> int -> 'a t -> int -> int -> unit
(** [blit from i into j len] copies [len] elements from the first array (** [blit from i into j len] copies [len] elements from the first array
@ -52,18 +52,18 @@ val blit : 'a t -> int -> 'a t -> int -> int -> unit
val reverse_in_place : 'a t -> unit val reverse_in_place : 'a t -> unit
(** Reverse the array in place *) (** Reverse the array in place *)
val sorted : f:('a -> 'a -> int) -> 'a t -> 'a array val sorted : ('a -> 'a -> int) -> 'a t -> 'a array
(** [sorted cmp a] makes a copy of [a] and sorts it with [cmp]. (** [sorted cmp a] makes a copy of [a] and sorts it with [cmp].
@since NEXT_RELEASE *) @since NEXT_RELEASE *)
val sort_indices : f:('a -> 'a -> int) -> 'a t -> int array val sort_indices : ('a -> 'a -> int) -> 'a t -> int array
(** [sort_indices cmp a] returns a new array [b], with the same length as [a], (** [sort_indices cmp a] returns a new array [b], with the same length as [a],
such that [b.(i)] is the index of the [i]-th element of [a] in [sort cmp a]. such that [b.(i)] is the index of the [i]-th element of [a] in [sort cmp a].
In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a]. In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a].
[a] is not modified. [a] is not modified.
@since NEXT_RELEASE *) @since NEXT_RELEASE *)
val sort_ranking : f:('a -> 'a -> int) -> 'a t -> int array val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array
(** [sort_ranking cmp a] returns a new array [b], with the same length as [a], (** [sort_ranking cmp a] returns a new array [b], with the same length as [a],
such that [b.(i)] is the position in [sorted cmp a] of the [i]-th such that [b.(i)] is the position in [sorted cmp a] of the [i]-th
element of [a]. element of [a].
@ -75,31 +75,31 @@ val sort_ranking : f:('a -> 'a -> int) -> 'a t -> int array
[lookup_exn a.(i) (sorted a) = (sorted_ranking a).(i)] [lookup_exn a.(i) (sorted a) = (sorted_ranking a).(i)]
@since NEXT_RELEASE *) @since NEXT_RELEASE *)
val find : f:('a -> 'b option) -> 'a t -> 'b option val find : ('a -> 'b option) -> 'a t -> 'b option
(** [find f a] returns [Some y] if there is an element [x] such (** [find f a] returns [Some y] if there is an element [x] such
that [f x = Some y], else it returns [None] *) that [f x = Some y], else it returns [None] *)
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
(** Like {!find}, but also pass the index to the predicate function. (** Like {!find}, but also pass the index to the predicate function.
@since 0.3.4 *) @since 0.3.4 *)
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option val find_idx : ('a -> bool) -> 'a t -> (int * 'a) option
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l], (** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
and [p x] holds. Otherwise returns [None] and [p x] holds. Otherwise returns [None]
@since 0.3.4 *) @since 0.3.4 *)
val lookup : ?cmp:'a ord -> key:'a -> 'a t -> int option val lookup : ?cmp:'a ord -> 'a -> 'a t -> int option
(** Lookup the index of some value in a sorted array. (** Lookup the index of some value in a sorted array.
@return [None] if the key is not present, or @return [None] if the key is not present, or
[Some i] ([i] the index of the key) otherwise *) [Some i] ([i] the index of the key) otherwise *)
val lookup_exn : ?cmp:'a ord -> key:'a -> 'a t -> int val lookup_exn : ?cmp:'a ord -> 'a -> 'a t -> int
(** Same as {!lookup_exn}, but (** Same as {!lookup_exn}, but
@raise Not_found if the key is not present *) @raise Not_found if the key is not present *)
val bsearch : ?cmp:('a -> 'a -> int) -> key:'a -> 'a t -> val bsearch : ?cmp:('a -> 'a -> int) -> 'a -> 'a t ->
[ `All_lower | `All_bigger | `Just_after of int | `Empty | `At of int ] [ `All_lower | `All_bigger | `Just_after of int | `Empty | `At of int ]
(** [bsearch ?cmp key arr] finds the index of the object [key] in the array [arr], (** [bsearch ?cmp x arr] finds the index of the object [x] in the array [arr],
provided [arr] is {b sorted} using [cmp]. If the array is not sorted, provided [arr] is {b sorted} using [cmp]. If the array is not sorted,
the result is not specified (may raise Invalid_argument). the result is not specified (may raise Invalid_argument).
@ -107,35 +107,35 @@ val bsearch : ?cmp:('a -> 'a -> int) -> key:'a -> 'a t ->
(dichotomic search). (dichotomic search).
@return @return
- [`At i] if [cmp arr.(i) key = 0] (for some i) - [`At i] if [cmp arr.(i) x = 0] (for some i)
- [`All_lower] if all elements of [arr] are lower than [key] - [`All_lower] if all elements of [arr] are lower than [x]
- [`All_bigger] if all elements of [arr] are bigger than [key] - [`All_bigger] if all elements of [arr] are bigger than [x]
- [`Just_after i] if [arr.(i) < key < arr.(i+1)] - [`Just_after i] if [arr.(i) < x < arr.(i+1)]
- [`Empty] if the array is empty - [`Empty] if the array is empty
@raise Invalid_argument if the array is found to be unsorted w.r.t [cmp] @raise Invalid_argument if the array is found to be unsorted w.r.t [cmp]
@since 0.13 *) @since 0.13 *)
val for_all : f:('a -> bool) -> 'a t -> bool val for_all : ('a -> bool) -> 'a t -> bool
val for_all2 : f:('a -> 'b -> bool) -> 'a t -> 'b t -> bool val for_all2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** Forall on pairs of arrays. (** Forall on pairs of arrays.
@raise Invalid_argument if they have distinct lengths @raise Invalid_argument if they have distinct lengths
allow different types @since 0.20 *) allow different types @since 0.20 *)
val exists : f:('a -> bool) -> 'a t -> bool val exists : ('a -> bool) -> 'a t -> bool
val exists2 : f:('a -> 'b -> bool) -> 'a t -> 'b t -> bool val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** Exists on pairs of arrays. (** Exists on pairs of arrays.
@raise Invalid_argument if they have distinct lengths @raise Invalid_argument if they have distinct lengths
allow different types @since 0.20 *) allow different types @since 0.20 *)
val fold2 : f:('acc -> 'a -> 'b -> 'acc) -> init:'acc -> 'a t -> 'b t -> 'acc val fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc
(** Fold on two arrays stepwise. (** Fold on two arrays stepwise.
@raise Invalid_argument if they have distinct lengths @raise Invalid_argument if they have distinct lengths
@since 0.20 *) @since 0.20 *)
val iter2 : f:('a -> 'b -> unit) -> 'a t -> 'b t -> unit val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
(** Iterate on two arrays stepwise. (** Iterate on two arrays stepwise.
@raise Invalid_argument if they have distinct lengths @raise Invalid_argument if they have distinct lengths
@since 0.20 *) @since 0.20 *)
@ -162,9 +162,9 @@ val pp: ?sep:string -> 'a printer -> 'a t printer
val pp_i: ?sep:string -> (int -> 'a printer) -> 'a t printer val pp_i: ?sep:string -> (int -> 'a printer) -> 'a t printer
(** Print an array, giving the printing function both index and item *) (** Print an array, giving the printing function both index and item *)
val map : f:('a -> 'b) -> 'a t -> 'b t val map : ('a -> 'b) -> 'a t -> 'b t
val map2 : f:('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** Map on two arrays stepwise. (** Map on two arrays stepwise.
@raise Invalid_argument if they have distinct lengths @raise Invalid_argument if they have distinct lengths
@since 0.20 *) @since 0.20 *)
@ -173,14 +173,14 @@ val rev : 'a t -> 'a t
(** Copy + reverse in place (** Copy + reverse in place
@since 0.20 *) @since 0.20 *)
val filter : f:('a -> bool) -> 'a t -> 'a t val filter : ('a -> bool) -> 'a t -> 'a t
(** Filter elements out of the array. Only the elements satisfying (** Filter elements out of the array. Only the elements satisfying
the given predicate will be kept. *) the given predicate will be kept. *)
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t val filter_map : ('a -> 'b option) -> 'a t -> 'b t
(** Map each element into another value, or discard it *) (** Map each element into another value, or discard it *)
val flat_map : f:('a -> 'b t) -> 'a t -> 'b array val flat_map : ('a -> 'b t) -> 'a t -> 'b array
(** Transform each element into an array, then flatten *) (** Transform each element into an array, then flatten *)
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t val (>>=) : 'a t -> ('a -> 'b t) -> 'b t

1
src/core/CCArrayLabels.ml Symbolic link
View file

@ -0,0 +1 @@
CCArray.ml

229
src/core/CCArrayLabels.mli Normal file
View file

@ -0,0 +1,229 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Array utils} *)
type 'a sequence = ('a -> unit) -> unit
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
type 'a gen = unit -> 'a option
type 'a equal = 'a -> 'a -> bool
type 'a ord = 'a -> 'a -> int
type 'a random_gen = Random.State.t -> 'a
type 'a printer = Format.formatter -> 'a -> unit
(** {2 Arrays} *)
type 'a t = 'a array
val empty : 'a t
val equal : 'a equal -> 'a t equal
val compare : 'a ord -> 'a t ord
val get : 'a t -> int -> 'a
val get_safe : 'a t -> int -> 'a option
(** [get_safe a i] returns [Some a.(i)] if [i] is a valid index
@since 0.18 *)
val set : 'a t -> int -> 'a -> unit
val length : _ t -> int
val fold : f:('a -> 'b -> 'a) -> init:'a -> 'b t -> 'a
val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a
(** Fold left on array, with index *)
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a
(** Fold left on array until a stop condition via [('a, `Stop)] is
indicated by the accumulator
@since 0.8 *)
val iter : f:('a -> unit) -> 'a t -> unit
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit
val blit : 'a t -> int -> 'a t -> int -> int -> unit
(** [blit from i into j len] copies [len] elements from the first array
to the second. See {!Array.blit}. *)
val reverse_in_place : 'a t -> unit
(** Reverse the array in place *)
val sorted : f:('a -> 'a -> int) -> 'a t -> 'a array
(** [sorted cmp a] makes a copy of [a] and sorts it with [cmp].
@since NEXT_RELEASE *)
val sort_indices : f:('a -> 'a -> int) -> 'a t -> int array
(** [sort_indices cmp a] returns a new array [b], with the same length as [a],
such that [b.(i)] is the index of the [i]-th element of [a] in [sort cmp a].
In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a].
[a] is not modified.
@since NEXT_RELEASE *)
val sort_ranking : f:('a -> 'a -> int) -> 'a t -> int array
(** [sort_ranking cmp a] returns a new array [b], with the same length as [a],
such that [b.(i)] is the position in [sorted cmp a] of the [i]-th
element of [a].
[a] is not modified.
In other words, [map (fun i -> (sorted cmp a).(i)) (sort_ranking cmp a) = a].
Without duplicates, we also have
[lookup_exn a.(i) (sorted a) = (sorted_ranking a).(i)]
@since NEXT_RELEASE *)
val find : f:('a -> 'b option) -> 'a t -> 'b option
(** [find f a] returns [Some y] if there is an element [x] such
that [f x = Some y], else it returns [None] *)
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
(** Like {!find}, but also pass the index to the predicate function.
@since 0.3.4 *)
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
and [p x] holds. Otherwise returns [None]
@since 0.3.4 *)
val lookup : ?cmp:'a ord -> key:'a -> 'a t -> int option
(** Lookup the index of some value in a sorted array.
@return [None] if the key is not present, or
[Some i] ([i] the index of the key) otherwise *)
val lookup_exn : ?cmp:'a ord -> key:'a -> 'a t -> int
(** Same as {!lookup_exn}, but
@raise Not_found if the key is not present *)
val bsearch : ?cmp:('a -> 'a -> int) -> key:'a -> 'a t ->
[ `All_lower | `All_bigger | `Just_after of int | `Empty | `At of int ]
(** [bsearch ?cmp key arr] finds the index of the object [key] in the array [arr],
provided [arr] is {b sorted} using [cmp]. If the array is not sorted,
the result is not specified (may raise Invalid_argument).
Complexity: O(log n) where n is the length of the array
(dichotomic search).
@return
- [`At i] if [cmp arr.(i) key = 0] (for some i)
- [`All_lower] if all elements of [arr] are lower than [key]
- [`All_bigger] if all elements of [arr] are bigger than [key]
- [`Just_after i] if [arr.(i) < key < arr.(i+1)]
- [`Empty] if the array is empty
@raise Invalid_argument if the array is found to be unsorted w.r.t [cmp]
@since 0.13 *)
val for_all : f:('a -> bool) -> 'a t -> bool
val for_all2 : f:('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** Forall on pairs of arrays.
@raise Invalid_argument if they have distinct lengths
allow different types @since 0.20 *)
val exists : f:('a -> bool) -> 'a t -> bool
val exists2 : f:('a -> 'b -> bool) -> 'a t -> 'b t -> bool
(** Exists on pairs of arrays.
@raise Invalid_argument if they have distinct lengths
allow different types @since 0.20 *)
val fold2 : f:('acc -> 'a -> 'b -> 'acc) -> init:'acc -> 'a t -> 'b t -> 'acc
(** Fold on two arrays stepwise.
@raise Invalid_argument if they have distinct lengths
@since 0.20 *)
val iter2 : f:('a -> 'b -> unit) -> 'a t -> 'b t -> unit
(** Iterate on two arrays stepwise.
@raise Invalid_argument if they have distinct lengths
@since 0.20 *)
val shuffle : 'a t -> unit
(** Shuffle randomly the array, in place *)
val shuffle_with : Random.State.t -> 'a t -> unit
(** Like shuffle but using a specialized random state *)
val random_choose : 'a t -> 'a random_gen
(** Choose an element randomly.
@raise Not_found if the array/slice is empty *)
val to_seq : 'a t -> 'a sequence
val to_gen : 'a t -> 'a gen
val to_klist : 'a t -> 'a klist
(** {2 IO} *)
val pp: ?sep:string -> 'a printer -> 'a t printer
(** Print an array of items with printing function *)
val pp_i: ?sep:string -> (int -> 'a printer) -> 'a t printer
(** Print an array, giving the printing function both index and item *)
val map : f:('a -> 'b) -> 'a t -> 'b t
val map2 : f:('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** Map on two arrays stepwise.
@raise Invalid_argument if they have distinct lengths
@since 0.20 *)
val rev : 'a t -> 'a t
(** Copy + reverse in place
@since 0.20 *)
val filter : f:('a -> bool) -> 'a t -> 'a t
(** Filter elements out of the array. Only the elements satisfying
the given predicate will be kept. *)
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t
(** Map each element into another value, or discard it *)
val flat_map : f:('a -> 'b t) -> 'a t -> 'b array
(** Transform each element into an array, then flatten *)
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
(** Infix version of {!flat_map} *)
val (>>|) : 'a t -> ('a -> 'b) -> 'b t
(** Infix version of {!map}
@since 0.8 *)
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
(** Infix version of {!map}
@since 0.8 *)
val except_idx : 'a t -> int -> 'a list
(** Remove given index, obtaining the list of the other elements *)
val (--) : int -> int -> int t
(** Range array *)
val (--^) : int -> int -> int t
(** Range array, excluding right bound
@since 0.17 *)
val random : 'a random_gen -> 'a t random_gen
val random_non_empty : 'a random_gen -> 'a t random_gen
val random_len : int -> 'a random_gen -> 'a t random_gen
(** {2 Generic Functions} *)
module type MONO_ARRAY = sig
type elt
type t
val length : t -> int
val get : t -> int -> elt
val set : t -> int -> elt -> unit
end
val sort_generic :
(module MONO_ARRAY with type t = 'arr and type elt = 'elt) ->
?cmp:('elt -> 'elt -> int) -> 'arr -> unit
(** Sort the array, without allocating (eats stack space though). Performance
might be lower than {!Array.sort}.
@since 0.14 *)

View file

@ -18,7 +18,7 @@ let is_empty = function
(* max depth for direct recursion *) (* max depth for direct recursion *)
let direct_depth_default_ = 1000 let direct_depth_default_ = 1000
let map ~f l = let map f l =
let rec direct f i l = match l with let rec direct f i l = match l with
| [] -> [] | [] -> []
| [x] -> [f x] | [x] -> [f x]
@ -40,7 +40,7 @@ let map ~f l =
List.rev (List.rev_map f l) = map f l) List.rev (List.rev_map f l) = map f l)
*) *)
let (>|=) l f = map ~f:f l let (>|=) l f = map f l
let direct_depth_append_ = 10_000 let direct_depth_append_ = 10_000
@ -78,7 +78,7 @@ let cons_maybe o l = match o with
let direct_depth_filter_ = 10_000 let direct_depth_filter_ = 10_000
let filter ~f l = let filter p l =
let rec direct i p l = match l with let rec direct i p l = match l with
| [] -> [] | [] -> []
| _ when i=0 -> safe p l [] | _ when i=0 -> safe p l []
@ -89,7 +89,7 @@ let filter ~f l =
| x::l' when not (p x) -> safe p l' acc | x::l' when not (p x) -> safe p l' acc
| x::l' -> safe p l' (x::acc) | x::l' -> safe p l' (x::acc)
in in
direct direct_depth_filter_ f l direct direct_depth_filter_ p l
(*$= & ~printer:CCInt.to_string (*$= & ~printer:CCInt.to_string
500 (filter (fun x->x mod 2 = 0) (1 -- 1000) |> List.length) 500 (filter (fun x->x mod 2 = 0) (1 -- 1000) |> List.length)
@ -122,38 +122,37 @@ let fold_right f l acc =
l = fold_right (fun x y->x::y) l []) l = fold_right (fun x y->x::y) l [])
*) *)
let rec fold_while ~f ~init:acc = function let rec fold_while f acc = function
| [] -> acc | [] -> acc
| e::l -> let acc, cont = f acc e in | e::l -> let acc, cont = f acc e in
match cont with match cont with
| `Stop -> acc | `Stop -> acc
| `Continue -> fold_while ~f ~init:acc l | `Continue -> fold_while f acc l
(*$T (*$T
fold_while ~f:(fun acc b -> if b then acc+1, `Continue else acc, `Stop) \ fold_while (fun acc b -> if b then acc+1, `Continue else acc, `Stop) 0 [true;true;false;true] = 2
~init:0 [true;true;false;true] = 2
*) *)
let fold_map ~f ~init l = let fold_map f acc l =
let rec aux f acc map_acc l = match l with let rec aux f acc map_acc l = match l with
| [] -> acc, List.rev map_acc | [] -> acc, List.rev map_acc
| x :: l' -> | x :: l' ->
let acc, y = f acc x in let acc, y = f acc x in
aux f acc (y :: map_acc) l' aux f acc (y :: map_acc) l'
in in
aux f init [] l aux f acc [] l
(*$= (*$=
(6, ["1"; "2"; "3"]) \ (6, ["1"; "2"; "3"]) \
(fold_map ~f:(fun acc x->acc+x, string_of_int x) ~init:0 [1;2;3]) (fold_map (fun acc x->acc+x, string_of_int x) 0 [1;2;3])
*) *)
(*$Q (*$Q
Q.(list int) (fun l -> \ Q.(list int) (fun l -> \
fold_map ~f:(fun acc x -> x::acc, x) ~init:[] l = (List.rev l, l)) fold_map (fun acc x -> x::acc, x) [] l = (List.rev l, l))
*) *)
let fold_map2 ~f ~init l1 l2 = let fold_map2 f acc l1 l2 =
let rec aux f acc map_acc l1 l2 = match l1, l2 with let rec aux f acc map_acc l1 l2 = match l1, l2 with
| [], [] -> acc, List.rev map_acc | [], [] -> acc, List.rev map_acc
| [], _ | [], _
@ -162,56 +161,56 @@ let fold_map2 ~f ~init l1 l2 =
let acc, y = f acc x1 x2 in let acc, y = f acc x1 x2 in
aux f acc (y :: map_acc) l1' l2' aux f acc (y :: map_acc) l1' l2'
in in
aux f init [] l1 l2 aux f acc [] l1 l2
(*$= (*$=
(310, ["1 10"; "2 0"; "3 100"]) \ (310, ["1 10"; "2 0"; "3 100"]) \
(fold_map2 ~f:(fun acc x y->acc+x*y, string_of_int x ^ " " ^ string_of_int y) \ (fold_map2 (fun acc x y->acc+x*y, string_of_int x ^ " " ^ string_of_int y) \
~init:0 [1;2;3] [10;0;100]) 0 [1;2;3] [10;0;100])
*) *)
(*$T (*$T
(try ignore (fold_map2 ~f:(fun _ _ _ -> assert false) ~init:42 [] [1]); false \ (try ignore (fold_map2 (fun _ _ _ -> assert false) 42 [] [1]); false \
with Invalid_argument _ -> true) with Invalid_argument _ -> true)
*) *)
let fold_filter_map ~f ~init l = let fold_filter_map f acc l =
let rec aux f acc map_acc l = match l with let rec aux f acc map_acc l = match l with
| [] -> acc, List.rev map_acc | [] -> acc, List.rev map_acc
| x :: l' -> | x :: l' ->
let acc, y = f acc x in let acc, y = f acc x in
aux f acc (cons_maybe y map_acc) l' aux f acc (cons_maybe y map_acc) l'
in in
aux f init [] l aux f acc [] l
(*$= & ~printer:Q.Print.(pair int (list int)) (*$= & ~printer:Q.Print.(pair int (list int))
(List.fold_left (+) 0 (1--10), [2;4;6;8;10]) \ (List.fold_left (+) 0 (1--10), [2;4;6;8;10]) \
(fold_filter_map ~f:(fun acc x -> acc+x, if x mod 2 = 0 then Some x else None) \ (fold_filter_map (fun acc x -> acc+x, if x mod 2 = 0 then Some x else None) \
~init:0 (1--10)) 0 (1--10))
*) *)
let fold_flat_map ~f ~init l = let fold_flat_map f acc l =
let rec aux f acc map_acc l = match l with let rec aux f acc map_acc l = match l with
| [] -> acc, List.rev map_acc | [] -> acc, List.rev map_acc
| x :: l' -> | x :: l' ->
let acc, y = f acc x in let acc, y = f acc x in
aux f acc (List.rev_append y map_acc) l' aux f acc (List.rev_append y map_acc) l'
in in
aux f init [] l aux f acc [] l
(*$= (*$=
(6, ["1"; "a1"; "2"; "a2"; "3"; "a3"]) \ (6, ["1"; "a1"; "2"; "a2"; "3"; "a3"]) \
(let pf = Printf.sprintf in \ (let pf = Printf.sprintf in \
fold_flat_map ~f:(fun acc x->acc+x, [pf "%d" x; pf "a%d" x]) ~init:0 [1;2;3]) fold_flat_map (fun acc x->acc+x, [pf "%d" x; pf "a%d" x]) 0 [1;2;3])
*) *)
(*$Q (*$Q
Q.(list int) (fun l -> \ Q.(list int) (fun l -> \
fold_flat_map ~f:(fun acc x -> x::acc, [x;x+10]) ~init:[] l = \ fold_flat_map (fun acc x -> x::acc, [x;x+10]) [] l = \
(List.rev l, flat_map ~f:(fun x->[x;x+10]) l) ) (List.rev l, flat_map (fun x->[x;x+10]) l) )
*) *)
let init len ~f = let init len f =
let rec init_rec acc i f = let rec init_rec acc i f =
if i=0 then f i :: acc if i=0 then f i :: acc
else init_rec (f i :: acc) (i-1) f else init_rec (f i :: acc) (i-1) f
@ -221,9 +220,9 @@ let init len ~f =
else init_rec [] (len-1) f else init_rec [] (len-1) f
(*$T (*$T
init 0 ~f:(fun _ -> 0) = [] init 0 (fun _ -> 0) = []
init 1 ~f:(fun x->x) = [0] init 1 (fun x->x) = [0]
init 1000 ~f:(fun x->x) = 0--999 init 1000 (fun x->x) = 0--999
*) *)
let rec compare f l1 l2 = match l1, l2 with let rec compare f l1 l2 = match l1, l2 with
@ -243,7 +242,7 @@ let rec equal f l1 l2 = match l1, l2 with
equal CCInt.equal (1--1_000_000) (1--1_000_000) equal CCInt.equal (1--1_000_000) (1--1_000_000)
*) *)
let flat_map ~f l = let flat_map f l =
let rec aux f l kont = match l with let rec aux f l kont = match l with
| [] -> kont [] | [] -> kont []
| x::l' -> | x::l' ->
@ -267,19 +266,19 @@ let flatten l = fold_right append l []
(*$T (*$T
flatten [[1]; [2;3;4]; []; []; [5;6]] = 1--6 flatten [[1]; [2;3;4]; []; []; [5;6]] = 1--6
flatten (init 300_001 ~f:(fun x->[x])) = 0--300_000 flatten (init 300_001 (fun x->[x])) = 0--300_000
*) *)
let product ~f l1 l2 = let product f l1 l2 =
flat_map ~f:(fun x -> map ~f:(fun y -> f x y) l2) l1 flat_map (fun x -> map (fun y -> f x y) l2) l1
let fold_product ~f ~init l1 l2 = let fold_product f acc l1 l2 =
List.fold_left List.fold_left
(fun acc x1 -> (fun acc x1 ->
List.fold_left List.fold_left
(fun acc x2 -> f acc x1 x2) (fun acc x2 -> f acc x1 x2)
acc l2) acc l2
init l1 ) acc l1
let diagonal l = let diagonal l =
let rec gen acc l = match l with let rec gen acc l = match l with
@ -297,7 +296,7 @@ let diagonal l =
diagonal [1;2;3] |> List.sort Pervasives.compare = [1, 2; 1, 3; 2, 3] diagonal [1;2;3] |> List.sort Pervasives.compare = [1, 2; 1, 3; 2, 3]
*) *)
let partition_map ~f l = let partition_map f l =
let rec iter f l1 l2 l = match l with let rec iter f l1 l2 l = match l with
| [] -> List.rev l1, List.rev l2 | [] -> List.rev l1, List.rev l2
| x :: tl -> | x :: tl ->
@ -310,11 +309,11 @@ let partition_map ~f l =
(*$R (*$R
let l1, l2 = let l1, l2 =
partition_map ~f:(function partition_map (function
| n when n = 0 -> `Drop | n when n = 0 -> `Drop
| n when n mod 2 = 0 -> `Left n | n when n mod 2 = 0 -> `Left n
| n -> `Right n) | n -> `Right n
[0;1;2;3;4] ) [0;1;2;3;4]
in in
assert_equal [2;4] l1; assert_equal [2;4] l1;
assert_equal [1;3] l2 assert_equal [1;3] l2
@ -322,13 +321,13 @@ let partition_map ~f l =
let return x = [x] let return x = [x]
let (>>=) l f = flat_map ~f l let (>>=) l f = flat_map f l
let (<$>) f x = map ~f x let (<$>) = map
let pure = return let pure = return
let (<*>) funs l = product ~f:(fun f x -> f x) funs l let (<*>) funs l = product (fun f x -> f x) funs l
let sorted_merge ?(cmp=Pervasives.compare) l1 l2 = let sorted_merge ?(cmp=Pervasives.compare) l1 l2 =
let rec recurse cmp acc l1 l2 = match l1,l2 with let rec recurse cmp acc l1 l2 = match l1,l2 with
@ -531,7 +530,7 @@ let split = take_drop
l1 @ l2 = l ) l1 @ l2 = l )
*) *)
let take_while ~f l = let take_while p l =
let rec direct i p l = match l with let rec direct i p l = match l with
| [] -> [] | [] -> []
| _ when i=0 -> safe p [] l | _ when i=0 -> safe p [] l
@ -542,13 +541,13 @@ let take_while ~f l =
| x :: l' -> | x :: l' ->
if p x then safe p (x::acc) l' else List.rev acc if p x then safe p (x::acc) l' else List.rev acc
in in
direct direct_depth_default_ f l direct direct_depth_default_ p l
(*$T (*$T
take_while ~f:(fun x->x<10) (1 -- 20) = (1--9) take_while (fun x->x<10) (1 -- 20) = (1--9)
take_while ~f:(fun x->x <> 0) [0;1;2;3] = [] take_while (fun x->x <> 0) [0;1;2;3] = []
take_while ~f:(fun _ -> true) [] = [] take_while (fun _ -> true) [] = []
take_while ~f:(fun _ -> true) (1--10) = (1--10) take_while (fun _ -> true) (1--10) = (1--10)
*) *)
(*$Q (*$Q
@ -557,9 +556,9 @@ let take_while ~f l =
List.for_all f l1) List.for_all f l1)
*) *)
let rec drop_while ~f l = match l with let rec drop_while p l = match l with
| [] -> [] | [] -> []
| x :: l' -> if f x then drop_while ~f l' else l | x :: l' -> if p x then drop_while p l' else l
(*$Q (*$Q
Q.(pair (fun1 small_int bool) (list small_int)) (fun (f,l) -> \ Q.(pair (fun1 small_int bool) (list small_int)) (fun (f,l) -> \
@ -588,23 +587,23 @@ let rec last_opt = function
None (last_opt []) None (last_opt [])
*) *)
let rec find_pred ~f l = match l with let rec find_pred p l = match l with
| [] -> None | [] -> None
| x :: _ when f x -> Some x | x :: _ when p x -> Some x
| _ :: tl -> find_pred ~f tl | _ :: tl -> find_pred p tl
let find_pred_exn ~f l = match find_pred ~f l with let find_pred_exn p l = match find_pred p l with
| None -> raise Not_found | None -> raise Not_found
| Some x -> x | Some x -> x
(*$T (*$T
find_pred ~f:((=) 4) [1;2;5;4;3;0] = Some 4 find_pred ((=) 4) [1;2;5;4;3;0] = Some 4
find_pred ~f:(fun _ -> true) [] = None find_pred (fun _ -> true) [] = None
find_pred ~f:(fun _ -> false) (1 -- 10) = None find_pred (fun _ -> false) (1 -- 10) = None
find_pred ~f:(fun x -> x < 10) (1 -- 9) = Some 1 find_pred (fun x -> x < 10) (1 -- 9) = Some 1
*) *)
let find_mapi ~f l = let find_mapi f l =
let rec aux f i = function let rec aux f i = function
| [] -> None | [] -> None
| x::l' -> | x::l' ->
@ -613,32 +612,32 @@ let find_mapi ~f l =
| None -> aux f (i+1) l' | None -> aux f (i+1) l'
in aux f 0 l in aux f 0 l
let find_map ~f l = find_mapi ~f:(fun _ -> f) l let find_map f l = find_mapi (fun _ -> f) l
let find = find_map let find = find_map
let findi = find_mapi let findi = find_mapi
let find_idx ~f l = find_mapi ~f:(fun i x -> if f x then Some (i, x) else None) l let find_idx p l = find_mapi (fun i x -> if p x then Some (i, x) else None) l
(*$T (*$T
find (fun x -> if x=3 then Some "a" else None) [1;2;3;4] = Some "a" find (fun x -> if x=3 then Some "a" else None) [1;2;3;4] = Some "a"
find (fun x -> if x=3 then Some "a" else None) [1;2;4;5] = None find (fun x -> if x=3 then Some "a" else None) [1;2;4;5] = None
*) *)
let remove ?(eq=(=)) ~key l = let remove ?(eq=(=)) ~x l =
let rec remove' eq x acc l = match l with let rec remove' eq x acc l = match l with
| [] -> List.rev acc | [] -> List.rev acc
| y :: tail when eq x y -> remove' eq x acc tail | y :: tail when eq x y -> remove' eq x acc tail
| y :: tail -> remove' eq x (y::acc) tail | y :: tail -> remove' eq x (y::acc) tail
in in
remove' eq key [] l remove' eq x [] l
(*$T (*$T
remove ~key:1 [2;1;3;3;2;1] = [2;3;3;2] remove ~x:1 [2;1;3;3;2;1] = [2;3;3;2]
remove ~key:10 [1;2;3] = [1;2;3] remove ~x:10 [1;2;3] = [1;2;3]
*) *)
let filter_map ~f l = let filter_map f l =
let rec recurse acc l = match l with let rec recurse acc l = match l with
| [] -> List.rev acc | [] -> List.rev acc
| x::l' -> | x::l' ->
@ -719,32 +718,32 @@ let inter ?(eq=(=)) l1 l2 =
inter [1;2;4] [2;3;4;5] = [2;4] inter [1;2;4] [2;3;4;5] = [2;4]
*) *)
let mapi ~f l = let mapi f l =
let r = ref 0 in let r = ref 0 in
map l map
~f:(fun x -> (fun x ->
let y = f !r x in let y = f !r x in
incr r; incr r; y
y) ) l
(*$T (*$T
mapi ~f:(fun i x -> i*x) [10;10;10] = [0;10;20] mapi (fun i x -> i*x) [10;10;10] = [0;10;20]
*) *)
let iteri ~f l = let iteri f l =
let rec aux f i l = match l with let rec aux f i l = match l with
| [] -> () | [] -> ()
| x::l' -> f i x; aux f (i+1) l' | x::l' -> f i x; aux f (i+1) l'
in aux f 0 l in aux f 0 l
let foldi ~f ~init l = let foldi f acc l =
let rec foldi f acc i l = match l with let rec foldi f acc i l = match l with
| [] -> acc | [] -> acc
| x::l' -> | x::l' ->
let acc = f acc i x in let acc = f acc i x in
foldi f acc (i+1) l' foldi f acc (i+1) l'
in in
foldi f init 0 l foldi f acc 0 l
let rec get_at_idx_exn i l = match l with let rec get_at_idx_exn i l = match l with
| [] -> raise Not_found | [] -> raise Not_found
@ -1019,7 +1018,7 @@ end
module Traverse(M : MONAD) = struct module Traverse(M : MONAD) = struct
open M open M
let map_m ~f l = let map_m f l =
let rec aux f acc l = match l with let rec aux f acc l = match l with
| [] -> return (List.rev acc) | [] -> return (List.rev acc)
| x::tail -> | x::tail ->
@ -1027,23 +1026,23 @@ module Traverse(M : MONAD) = struct
aux f (x' :: acc) tail aux f (x' :: acc) tail
in aux f [] l in aux f [] l
let rec map_m_par ~f l = match l with let rec map_m_par f l = match l with
| [] -> M.return [] | [] -> M.return []
| x::tl -> | x::tl ->
let x' = f x in let x' = f x in
let tl' = map_m_par ~f tl in let tl' = map_m_par f tl in
x' >>= fun x' -> x' >>= fun x' ->
tl' >>= fun tl' -> tl' >>= fun tl' ->
M.return (x'::tl') M.return (x'::tl')
let sequence_m l = map_m l ~f:(fun x->x) let sequence_m l = map_m (fun x->x) l
let rec fold_m ~f ~init l = match l with let rec fold_m f acc l = match l with
| [] -> return init | [] -> return acc
| x :: l' -> | x :: l' ->
f init x f acc x
>>= fun acc' -> >>= fun acc' ->
fold_m ~f ~init:acc' l' fold_m f acc' l'
end end
(** {2 Conversions} *) (** {2 Conversions} *)
@ -1055,7 +1054,7 @@ type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a type 'a random_gen = Random.State.t -> 'a
let random_len len g st = let random_len len g st =
init len ~f:(fun _ -> g st) init len (fun _ -> g st)
(*$T (*$T
random_len 10 CCInt.random_small (Random.State.make [||]) |> List.length = 10 random_len 10 CCInt.random_small (Random.State.make [||]) |> List.length = 10
@ -1077,7 +1076,7 @@ let random_choose l = match l with
let i = Random.State.int st len in let i = Random.State.int st len in
List.nth l i List.nth l i
let random_sequence l st = map l ~f:(fun g -> g st) let random_sequence l st = map (fun g -> g st) l
let to_seq l k = List.iter k l let to_seq l k = List.iter k l
let of_seq seq = let of_seq seq =

View file

@ -11,7 +11,7 @@ val is_empty : _ t -> bool
(** [is_empty l] returns [true] iff [l = []] (** [is_empty l] returns [true] iff [l = []]
@since 0.11 *) @since 0.11 *)
val map : f:('a -> 'b) -> 'a t -> 'b t val map : ('a -> 'b) -> 'a t -> 'b t
(** Safe version of map *) (** Safe version of map *)
val (>|=) : 'a t -> ('a -> 'b) -> 'b t val (>|=) : 'a t -> ('a -> 'b) -> 'b t
@ -32,38 +32,38 @@ val cons_maybe : 'a option -> 'a t -> 'a t
val (@) : 'a t -> 'a t -> 'a t val (@) : 'a t -> 'a t -> 'a t
val filter : f:('a -> bool) -> 'a t -> 'a t val filter : ('a -> bool) -> 'a t -> 'a t
(** Safe version of {!List.filter} *) (** Safe version of {!List.filter} *)
val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
(** Safe version of [fold_right] *) (** Safe version of [fold_right] *)
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
(** Fold until a stop condition via [('a, `Stop)] is (** Fold until a stop condition via [('a, `Stop)] is
indicated by the accumulator indicated by the accumulator
@since 0.8 *) @since 0.8 *)
val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a list -> 'acc * 'b list val fold_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a list -> 'acc * 'b list
(** [fold_map f acc l] is a [fold_left]-like function, but it also maps the (** [fold_map f acc l] is a [fold_left]-like function, but it also maps the
list to another list. list to another list.
@since 0.14 *) @since 0.14 *)
val fold_map2 : f:('acc -> 'a -> 'b -> 'acc * 'c) -> init:'acc -> 'a list -> 'b list -> 'acc * 'c list val fold_map2 : ('acc -> 'a -> 'b -> 'acc * 'c) -> 'acc -> 'a list -> 'b list -> 'acc * 'c list
(** [fold_map2] is to [fold_map] what [List.map2] is to [List.map]. (** [fold_map2] is to [fold_map] what [List.map2] is to [List.map].
@raise Invalid_argument if the lists do not have the same length @raise Invalid_argument if the lists do not have the same length
@since 0.16 *) @since 0.16 *)
val fold_filter_map : f:('acc -> 'a -> 'acc * 'b option) -> init:'acc -> 'a list -> 'acc * 'b list val fold_filter_map : ('acc -> 'a -> 'acc * 'b option) -> 'acc -> 'a list -> 'acc * 'b list
(** [fold_filter_map f acc l] is a [fold_left]-like function, but also (** [fold_filter_map f acc l] is a [fold_left]-like function, but also
generates a list of output in a way similar to {!filter_map} generates a list of output in a way similar to {!filter_map}
@since 0.17 *) @since 0.17 *)
val fold_flat_map : f:('acc -> 'a -> 'acc * 'b list) -> init:'acc -> 'a list -> 'acc * 'b list val fold_flat_map : ('acc -> 'a -> 'acc * 'b list) -> 'acc -> 'a list -> 'acc * 'b list
(** [fold_flat_map f acc l] is a [fold_left]-like function, but it also maps the (** [fold_flat_map f acc l] is a [fold_left]-like function, but it also maps the
list to a list of lists that is then [flatten]'d.. list to a list of lists that is then [flatten]'d..
@since 0.14 *) @since 0.14 *)
val init : int -> f:(int -> 'a) -> 'a t val init : int -> (int -> 'a) -> 'a t
(** Similar to {!Array.init} (** Similar to {!Array.init}
@since 0.6 *) @since 0.6 *)
@ -71,23 +71,23 @@ val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
val flat_map : f:('a -> 'b t) -> 'a t -> 'b t val flat_map : ('a -> 'b t) -> 'a t -> 'b t
(** Map and flatten at the same time (safe). Evaluation order is not guaranteed. *) (** Map and flatten at the same time (safe). Evaluation order is not guaranteed. *)
val flatten : 'a t t -> 'a t val flatten : 'a t t -> 'a t
(** Safe flatten *) (** Safe flatten *)
val product : f:('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t val product : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** Cartesian product of the two lists, with the given combinator *) (** Cartesian product of the two lists, with the given combinator *)
val fold_product : f:('c -> 'a -> 'b -> 'c) -> init:'c -> 'a t -> 'b t -> 'c val fold_product : ('c -> 'a -> 'b -> 'c) -> 'c -> 'a t -> 'b t -> 'c
(** Fold on the cartesian product *) (** Fold on the cartesian product *)
val diagonal : 'a t -> ('a * 'a) t val diagonal : 'a t -> ('a * 'a) t
(** All pairs of distinct positions of the list. [list_diagonal l] will (** All pairs of distinct positions of the list. [list_diagonal l] will
return the list of [List.nth i l, List.nth j l] if [i < j]. *) return the list of [List.nth i l, List.nth j l] if [i < j]. *)
val partition_map : f:('a -> [<`Left of 'b | `Right of 'c | `Drop]) -> val partition_map : ('a -> [<`Left of 'b | `Right of 'c | `Drop]) ->
'a list -> 'b list * 'c list 'a list -> 'b list * 'c list
(** [partition_map f l] maps [f] on [l] and gather results in lists: (** [partition_map f l] maps [f] on [l] and gather results in lists:
- if [f x = `Left y], adds [y] to the first list - if [f x = `Left y], adds [y] to the first list
@ -120,10 +120,10 @@ val take_drop : int -> 'a t -> 'a t * 'a t
(** [take_drop n l] returns [l1, l2] such that [l1 @ l2 = l] and (** [take_drop n l] returns [l1, l2] such that [l1 @ l2 = l] and
[length l1 = min (length l) n] *) [length l1 = min (length l) n] *)
val take_while : f:('a -> bool) -> 'a t -> 'a t val take_while : ('a -> bool) -> 'a t -> 'a t
(** @since 0.13 *) (** @since 0.13 *)
val drop_while : f:('a -> bool) -> 'a t -> 'a t val drop_while : ('a -> bool) -> 'a t -> 'a t
(** @since 0.13 *) (** @since 0.13 *)
val split : int -> 'a t -> 'a t * 'a t val split : int -> 'a t -> 'a t * 'a t
@ -142,44 +142,43 @@ val last_opt : 'a t -> 'a option
(** Last element. (** Last element.
@since 0.20 *) @since 0.20 *)
val find_pred : f:('a -> bool) -> 'a t -> 'a option val find_pred : ('a -> bool) -> 'a t -> 'a option
(** [find_pred p l] finds the first element of [l] that satisfies [p], (** [find_pred p l] finds the first element of [l] that satisfies [p],
or returns [None] if no element satisfies [p] or returns [None] if no element satisfies [p]
@since 0.11 *) @since 0.11 *)
val find_pred_exn : f:('a -> bool) -> 'a t -> 'a val find_pred_exn : ('a -> bool) -> 'a t -> 'a
(** Unsafe version of {!find_pred} (** Unsafe version of {!find_pred}
@raise Not_found if no such element is found @raise Not_found if no such element is found
@since 0.11 *) @since 0.11 *)
val find_map : f:('a -> 'b option) -> 'a t -> 'b option val find_map : ('a -> 'b option) -> 'a t -> 'b option
(** [find_map f l] traverses [l], applying [f] to each element. If for (** [find_map f l] traverses [l], applying [f] to each element. If for
some element [x], [f x = Some y], then [Some y] is returned. Otherwise some element [x], [f x = Some y], then [Some y] is returned. Otherwise
the call returns [None] the call returns [None]
@since 0.11 *) @since 0.11 *)
(* TODO remove *) val find : ('a -> 'b option) -> 'a list -> 'b option
val find : f:('a -> 'b option) -> 'a list -> 'b option
(** @deprecated since 0.11 in favor of {!find_map}, for the name is too confusing *) (** @deprecated since 0.11 in favor of {!find_map}, for the name is too confusing *)
val find_mapi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option val find_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b option
(** Like {!find_map}, but also pass the index to the predicate function. (** Like {!find_map}, but also pass the index to the predicate function.
@since 0.11 *) @since 0.11 *)
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
(** @deprecated since 0.11 in favor of {!find_mapi}, name is too confusing (** @deprecated since 0.11 in favor of {!find_mapi}, name is too confusing
@since 0.3.4 *) @since 0.3.4 *)
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option val find_idx : ('a -> bool) -> 'a t -> (int * 'a) option
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l], (** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
and [p x] holds. Otherwise returns [None] *) and [p x] holds. Otherwise returns [None] *)
val remove : ?eq:('a -> 'a -> bool) -> key:'a -> 'a t -> 'a t val remove : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> 'a t
(** [remove ~key l] removes every instance of [key] from [l]. Tailrec. (** [remove ~x l] removes every instance of [x] from [l]. Tailrec.
@param eq equality function @param eq equality function
@since 0.11 *) @since 0.11 *)
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t val filter_map : ('a -> 'b option) -> 'a t -> 'b t
(** Map and remove elements at the same time *) (** Map and remove elements at the same time *)
val sorted_merge : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list val sorted_merge : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
@ -225,11 +224,11 @@ val group_succ : ?eq:('a -> 'a -> bool) -> 'a list -> 'a list list
(** {2 Indices} *) (** {2 Indices} *)
val mapi : f:(int -> 'a -> 'b) -> 'a t -> 'b t val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit val iteri : (int -> 'a -> unit) -> 'a t -> unit
val foldi : f:('b -> int -> 'a -> 'b) -> init:'b -> 'a t -> 'b val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
(** Fold on list, with index *) (** Fold on list, with index *)
val get_at_idx : int -> 'a t -> 'a option val get_at_idx : int -> 'a t -> 'a option
@ -380,11 +379,11 @@ end
module Traverse(M : MONAD) : sig module Traverse(M : MONAD) : sig
val sequence_m : 'a M.t t -> 'a t M.t val sequence_m : 'a M.t t -> 'a t M.t
val fold_m : f:('b -> 'a -> 'b M.t) -> init:'b -> 'a t -> 'b M.t val fold_m : ('b -> 'a -> 'b M.t) -> 'b -> 'a t -> 'b M.t
val map_m : f:('a -> 'b M.t) -> 'a t -> 'b t M.t val map_m : ('a -> 'b M.t) -> 'a t -> 'b t M.t
val map_m_par : f:('a -> 'b M.t) -> 'a t -> 'b t M.t val map_m_par : ('a -> 'b M.t) -> 'a t -> 'b t M.t
(** Same as {!map_m} but [map_m_par f (x::l)] evaluates [f x] and (** Same as {!map_m} but [map_m_par f (x::l)] evaluates [f x] and
[f l] "in parallel" before combining their result (for instance [f l] "in parallel" before combining their result (for instance
in Lwt). *) in Lwt). *)

1
src/core/CCListLabels.ml Symbolic link
View file

@ -0,0 +1 @@
CCList.ml

441
src/core/CCListLabels.mli Normal file
View file

@ -0,0 +1,441 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 complements to list} *)
type 'a t = 'a list
val empty : 'a t
val is_empty : _ t -> bool
(** [is_empty l] returns [true] iff [l = []]
@since 0.11 *)
val map : f:('a -> 'b) -> 'a t -> 'b t
(** Safe version of map *)
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
(** Infix version of [map] with reversed arguments
@since 0.5 *)
val cons : 'a -> 'a t -> 'a t
(** [cons x l] is [x::l]
@since 0.12 *)
val append : 'a t -> 'a t -> 'a t
(** Safe version of append *)
val cons_maybe : 'a option -> 'a t -> 'a t
(** [cons_maybe (Some x) l] is [x :: l]
[cons_maybe None l] is [l]
@since 0.13 *)
val (@) : 'a t -> 'a t -> 'a t
val filter : f:('a -> bool) -> 'a t -> 'a t
(** Safe version of {!List.filter} *)
val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
(** Safe version of [fold_right] *)
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a
(** Fold until a stop condition via [('a, `Stop)] is
indicated by the accumulator
@since 0.8 *)
val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a list -> 'acc * 'b list
(** [fold_map f acc l] is a [fold_left]-like function, but it also maps the
list to another list.
@since 0.14 *)
val fold_map2 : f:('acc -> 'a -> 'b -> 'acc * 'c) -> init:'acc -> 'a list -> 'b list -> 'acc * 'c list
(** [fold_map2] is to [fold_map] what [List.map2] is to [List.map].
@raise Invalid_argument if the lists do not have the same length
@since 0.16 *)
val fold_filter_map : f:('acc -> 'a -> 'acc * 'b option) -> init:'acc -> 'a list -> 'acc * 'b list
(** [fold_filter_map f acc l] is a [fold_left]-like function, but also
generates a list of output in a way similar to {!filter_map}
@since 0.17 *)
val fold_flat_map : f:('acc -> 'a -> 'acc * 'b list) -> init:'acc -> 'a list -> 'acc * 'b list
(** [fold_flat_map f acc l] is a [fold_left]-like function, but it also maps the
list to a list of lists that is then [flatten]'d..
@since 0.14 *)
val init : int -> f:(int -> 'a) -> 'a t
(** Similar to {!Array.init}
@since 0.6 *)
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
val flat_map : f:('a -> 'b t) -> 'a t -> 'b t
(** Map and flatten at the same time (safe). Evaluation order is not guaranteed. *)
val flatten : 'a t t -> 'a t
(** Safe flatten *)
val product : f:('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** Cartesian product of the two lists, with the given combinator *)
val fold_product : f:('c -> 'a -> 'b -> 'c) -> init:'c -> 'a t -> 'b t -> 'c
(** Fold on the cartesian product *)
val diagonal : 'a t -> ('a * 'a) t
(** All pairs of distinct positions of the list. [list_diagonal l] will
return the list of [List.nth i l, List.nth j l] if [i < j]. *)
val partition_map : f:('a -> [<`Left of 'b | `Right of 'c | `Drop]) ->
'a list -> 'b list * 'c list
(** [partition_map f l] maps [f] on [l] and gather results in lists:
- if [f x = `Left y], adds [y] to the first list
- if [f x = `Right z], adds [z] to the second list
- if [f x = `Drop], ignores [x]
@since 0.11 *)
val pure : 'a -> 'a t
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
val return : 'a -> 'a t
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
val take : int -> 'a t -> 'a t
(** Take the [n] first elements, drop the rest *)
val drop : int -> 'a t -> 'a t
(** Drop the [n] first elements, keep the rest *)
val hd_tl : 'a t -> 'a * 'a t
(** [hd_tl (x :: l)] returns [hd, l].
@raise Failure if the list is empty
@since 0.16 *)
val take_drop : int -> 'a t -> 'a t * 'a t
(** [take_drop n l] returns [l1, l2] such that [l1 @ l2 = l] and
[length l1 = min (length l) n] *)
val take_while : f:('a -> bool) -> 'a t -> 'a t
(** @since 0.13 *)
val drop_while : f:('a -> bool) -> 'a t -> 'a t
(** @since 0.13 *)
val split : int -> 'a t -> 'a t * 'a t
(** Synonym to {!take_drop}
@deprecated since 0.13: conflict with the {!List.split} standard function *)
val last : int -> 'a t -> 'a t
(** [last n l] takes the last [n] elements of [l] (or less if
[l] doesn't have that many elements *)
val head_opt : 'a t -> 'a option
(** First element.
@since 0.20 *)
val last_opt : 'a t -> 'a option
(** Last element.
@since 0.20 *)
val find_pred : f:('a -> bool) -> 'a t -> 'a option
(** [find_pred p l] finds the first element of [l] that satisfies [p],
or returns [None] if no element satisfies [p]
@since 0.11 *)
val find_pred_exn : f:('a -> bool) -> 'a t -> 'a
(** Unsafe version of {!find_pred}
@raise Not_found if no such element is found
@since 0.11 *)
val find_map : f:('a -> 'b option) -> 'a t -> 'b option
(** [find_map f l] traverses [l], applying [f] to each element. If for
some element [x], [f x = Some y], then [Some y] is returned. Otherwise
the call returns [None]
@since 0.11 *)
(* TODO remove *)
val find : f:('a -> 'b option) -> 'a list -> 'b option
(** @deprecated since 0.11 in favor of {!find_map}, for the name is too confusing *)
val find_mapi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
(** Like {!find_map}, but also pass the index to the predicate function.
@since 0.11 *)
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
(** @deprecated since 0.11 in favor of {!find_mapi}, name is too confusing
@since 0.3.4 *)
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
and [p x] holds. Otherwise returns [None] *)
val remove : ?eq:('a -> 'a -> bool) -> key:'a -> 'a t -> 'a t
(** [remove ~key l] removes every instance of [key] from [l]. Tailrec.
@param eq equality function
@since 0.11 *)
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t
(** Map and remove elements at the same time *)
val sorted_merge : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
(** Merges elements from both sorted list *)
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list
(** Sort the list and remove duplicate elements *)
val sorted_merge_uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
(** [sorted_merge_uniq l1 l2] merges the sorted lists [l1] and [l2] and
removes duplicates
@since 0.10 *)
val is_sorted : ?cmp:('a -> 'a -> int) -> 'a list -> bool
(** [is_sorted l] returns [true] iff [l] is sorted (according to given order)
@param cmp the comparison function (default [Pervasives.compare])
@since 0.17 *)
val sorted_insert : ?cmp:('a -> 'a -> int) -> ?uniq:bool -> 'a -> 'a list -> 'a list
(** [sorted_insert x l] inserts [x] into [l] such that, if [l] was sorted,
then [sorted_insert x l] is sorted too.
@param uniq if true and [x] is already in sorted position in [l], then
[x] is not duplicated. Default [false] ([x] will be inserted in any case).
@since 0.17 *)
(*$Q
Q.(pair small_int (list small_int)) (fun (x,l) -> \
let l = List.sort Pervasives.compare l in \
is_sorted (sorted_insert x l))
*)
val uniq_succ : ?eq:('a -> 'a -> bool) -> 'a list -> 'a list
(** [uniq_succ l] removes duplicate elements that occur one next to the other.
Examples:
[uniq_succ [1;2;1] = [1;2;1]]
[uniq_succ [1;1;2] = [1;2]]
@since 0.10 *)
val group_succ : ?eq:('a -> 'a -> bool) -> 'a list -> 'a list list
(** [group_succ ~eq l] groups together consecutive elements that are equal
according to [eq]
@since 0.11 *)
(** {2 Indices} *)
val mapi : f:(int -> 'a -> 'b) -> 'a t -> 'b t
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit
val foldi : f:('b -> int -> 'a -> 'b) -> init:'b -> 'a t -> 'b
(** Fold on list, with index *)
val get_at_idx : int -> 'a t -> 'a option
val get_at_idx_exn : int -> 'a t -> 'a
(** Get the i-th element, or
@raise Not_found if the index is invalid *)
val set_at_idx : int -> 'a -> 'a t -> 'a t
(** Set i-th element (removes the old one), or does nothing if
index is too high *)
val insert_at_idx : int -> 'a -> 'a t -> 'a t
(** Insert at i-th position, between the two existing elements. If the
index is too high, append at the end of the list *)
val remove_at_idx : int -> 'a t -> 'a t
(** Remove element at given index. Does nothing if the index is
too high. *)
(** {2 Set Operators}
Those operations maintain the invariant that the list does not
contain duplicates (if it already satisfies it) *)
val add_nodup : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t
(** [add_nodup x set] adds [x] to [set] if it was not already present. Linear time.
@since 0.11 *)
val remove_one : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t
(** [remove_one x set] removes one occurrence of [x] from [set]. Linear time.
@since 0.11 *)
val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool
(** Membership to the list. Linear time *)
val subset : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> bool
(** Test for inclusion *)
val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
(** Remove duplicates w.r.t the equality predicate.
Complexity is quadratic in the length of the list, but the order
of elements is preserved. If you wish for a faster de-duplication
but do not care about the order, use {!sort_uniq}*)
val union : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t
(** List union. Complexity is product of length of inputs. *)
val inter : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t
(** List intersection. Complexity is product of length of inputs. *)
(** {2 Other Constructors} *)
val range_by : step:int -> int -> int -> int t
(** [range_by ~step i j] iterates on integers from [i] to [j] included,
where the difference between successive elements is [step].
use a negative [step] for a decreasing list.
@raise Invalid_argument if [step=0]
@since 0.18 *)
val range : int -> int -> int t
(** [range i j] iterates on integers from [i] to [j] included . It works
both for decreasing and increasing ranges *)
val range' : int -> int -> int t
(** Same as {!range} but the second bound is excluded.
For instance [range' 0 5 = [0;1;2;3;4]] *)
val (--) : int -> int -> int t
(** Infix alias for [range] *)
val (--^) : int -> int -> int t
(** Infix alias for [range']
@since 0.17 *)
val replicate : int -> 'a -> 'a t
(** Replicate the given element [n] times *)
val repeat : int -> 'a t -> 'a t
(** Concatenate the list with itself [n] times *)
(** {2 Association Lists} *)
module Assoc : sig
type ('a, 'b) t = ('a*'b) list
val get : ?eq:('a->'a->bool) -> 'a -> ('a,'b) t -> 'b option
(** Find the element *)
val get_exn : ?eq:('a->'a->bool) -> 'a -> ('a,'b) t -> 'b
(** Same as [get], but unsafe
@raise Not_found if the element is not present *)
val set : ?eq:('a->'a->bool) -> 'a -> 'b -> ('a,'b) t -> ('a,'b) t
(** Add the binding into the list (erase it if already present) *)
val mem : ?eq:('a->'a->bool) -> 'a -> ('a,_) t -> bool
(** [mem x l] returns [true] iff [x] is a key in [l]
@since 0.16 *)
val update :
?eq:('a->'a->bool) -> f:('b option -> 'b option) -> 'a -> ('a,'b) t -> ('a,'b) t
(** [update k ~f l] updates [l] on the key [k], by calling [f (get l k)]
and removing [k] if it returns [None], mapping [k] to [v'] if it
returns [Some v']
@since 0.16 *)
val remove : ?eq:('a->'a->bool) -> 'a -> ('a,'b) t -> ('a,'b) t
(** [remove x l] removes the first occurrence of [k] from [l].
@since 0.17 *)
end
(** {2 References on Lists}
@since 0.3.3 *)
module Ref : sig
type 'a t = 'a list ref
val push : 'a t -> 'a -> unit
val pop : 'a t -> 'a option
val pop_exn : 'a t -> 'a
(** Unsafe version of {!pop}.
@raise Failure if the list is empty *)
val create : unit -> 'a t
(** Create a new list reference *)
val clear : _ t -> unit
(** Remove all elements *)
val lift : ('a list -> 'b) -> 'a t -> 'b
(** Apply a list function to the content *)
val push_list : 'a t -> 'a list -> unit
(** Add elements of the list at the beginning of the list ref. Elements
at the end of the list will be at the beginning of the list ref *)
end
(** {2 Monadic Operations} *)
module type MONAD = sig
type 'a t
val return : 'a -> 'a t
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
end
module Traverse(M : MONAD) : sig
val sequence_m : 'a M.t t -> 'a t M.t
val fold_m : f:('b -> 'a -> 'b M.t) -> init:'b -> 'a t -> 'b M.t
val map_m : f:('a -> 'b M.t) -> 'a t -> 'b t M.t
val map_m_par : f:('a -> 'b M.t) -> 'a t -> 'b t M.t
(** Same as {!map_m} but [map_m_par f (x::l)] evaluates [f x] and
[f l] "in parallel" before combining their result (for instance
in Lwt). *)
end
(** {2 Conversions} *)
type 'a sequence = ('a -> unit) -> unit
type 'a gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
val random : 'a random_gen -> 'a t random_gen
val random_non_empty : 'a random_gen -> 'a t random_gen
val random_len : int -> 'a random_gen -> 'a t random_gen
val random_choose : 'a t -> 'a random_gen
(** Randomly choose an element in the list.
@raise Not_found if the list is empty *)
val random_sequence : 'a random_gen t -> 'a t random_gen
val to_seq : 'a t -> 'a sequence
val of_seq : 'a sequence -> 'a t
val to_gen : 'a t -> 'a gen
val of_gen : 'a gen -> 'a t
val to_klist : 'a t -> 'a klist
val of_klist : 'a klist -> 'a t
(** {2 Infix Operators}
It is convenient to {!open CCList.Infix} to access the infix operators
without cluttering the scope too much.
@since 0.16 *)
module Infix : sig
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
val (@) : 'a t -> 'a t -> 'a t
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
val (--) : int -> int -> int t
val (--^) : int -> int -> int t
(** @since 0.17 *)
end
(** {2 IO} *)
val pp : ?start:string -> ?stop:string -> ?sep:string ->
'a printer -> 'a t printer

View file

@ -604,7 +604,7 @@ module Make(Key : KEY)
aux acc t aux acc t
(*$T (*$T
let l = CCList.(1 -- 10 |> map ~f:(fun x->x,x)) in \ let l = CCList.(1 -- 10 |> map (fun x->x,x)) in \
M.of_list l \ M.of_list l \
|> M.fold ~f:(fun acc x y -> (x,y)::acc) ~x:[] \ |> M.fold ~f:(fun acc x y -> (x,y)::acc) ~x:[] \
|> List.sort Pervasives.compare = l |> List.sort Pervasives.compare = l
@ -720,7 +720,7 @@ module Make(Key : KEY)
end end
(*$R (*$R
let m = M.of_list CCList.( (501 -- 1000) @ (500 -- 1) |> map ~f:(fun i->i,i)) in let m = M.of_list CCList.( (501 -- 1000) @ (500 -- 1) |> map (fun i->i,i)) in
assert_equal ~printer:CCInt.to_string 1000 (M.cardinal m); assert_equal ~printer:CCInt.to_string 1000 (M.cardinal m);
assert_bool "check all get" assert_bool "check all get"
(Sequence.for_all (fun i -> i = M.get_exn i m) Sequence.(1 -- 1000)); (Sequence.for_all (fun i -> i = M.get_exn i m) Sequence.(1 -- 1000));

View file

@ -361,7 +361,7 @@ module MakeFull(K : KEY) : S with type key = K.t = struct
with Not_found -> None with Not_found -> None
(*$T (*$T
let m = CCList.(0 -- 1000 |> map ~f:(fun i->i,i) |> M.of_list) in \ let m = CCList.(0 -- 1000 |> map (fun i->i,i) |> M.of_list) in \
List.for_all (fun i -> M.nth_exn i m = (i,i)) CCList.(0--1000) List.for_all (fun i -> M.nth_exn i m = (i,i)) CCList.(0--1000)
*) *)