mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 03:05:28 -05:00
Generate unlabelled interfaces from labelled ones
* add unlabel.ml which parses interfaces and removes labels in function declarations and docstrings. This is a quick hack, but it does the job. * an attribute [@keep_label] can be added to the labelled arguments to mark labels like ~cmp which should stay in the "unlabelled" interface * While augmenting the labelled interfaces I stumbled across some inconsistencies between the currend labelled / non-labelled interfaces. I used the labelling that made most sense to me and added a "FIXME" comment. * Maybe we should break backwards compatibility at some point and name the comparison arguments to the sorting functions in CCArrayLabels.ml ~cmp instead of ~f ?
This commit is contained in:
parent
2a9795090b
commit
f6e1d81ed7
10 changed files with 582 additions and 172 deletions
8
Makefile
8
Makefile
|
|
@ -1,8 +1,10 @@
|
||||||
|
PROMOTE=$(if $(shell ocamlc -version |grep '4\.0[012]\.[0-9][0-9]*'), \
|
||||||
|
--ignore-promoted-rules, )
|
||||||
|
|
||||||
all: build test
|
all: build test
|
||||||
|
|
||||||
build:
|
build:
|
||||||
dune build @install
|
dune build $(PROMOTE) @install
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
dune runtest --no-buffer --force
|
dune runtest --no-buffer --force
|
||||||
|
|
@ -11,12 +13,12 @@ clean:
|
||||||
dune clean
|
dune clean
|
||||||
|
|
||||||
doc:
|
doc:
|
||||||
dune build @doc
|
dune build $(PROMOTE) @doc
|
||||||
|
|
||||||
BENCH_TARGETS=run_benchs.exe run_bench_hash.exe
|
BENCH_TARGETS=run_benchs.exe run_bench_hash.exe
|
||||||
|
|
||||||
benchs:
|
benchs:
|
||||||
dune build $(addprefix benchs/, $(BENCH_TARGETS))
|
dune build $(PROMOTE) $(addprefix benchs/, $(BENCH_TARGETS))
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
dune build examples/id_sexp.exe
|
dune build examples/id_sexp.exe
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ let do_not_test file =
|
||||||
is_suffix ~sub:"containers.ml" file ||
|
is_suffix ~sub:"containers.ml" file ||
|
||||||
is_suffix ~sub:"containers_top.ml" file ||
|
is_suffix ~sub:"containers_top.ml" file ||
|
||||||
is_suffix ~sub:"mkflags.ml" file ||
|
is_suffix ~sub:"mkflags.ml" file ||
|
||||||
|
is_suffix ~sub:"unlabel.ml" file ||
|
||||||
is_suffix ~sub:"utop.ml" file
|
is_suffix ~sub:"utop.ml" file
|
||||||
|
|
||||||
let prefix = "src"
|
let prefix = "src"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
(* AUTOGENERATED FROM CCArrayLabels.mli *)
|
||||||
|
|
||||||
(* 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. *)
|
||||||
|
|
||||||
|
|
@ -13,6 +14,10 @@ type 'a printer = Format.formatter -> 'a -> unit
|
||||||
|
|
||||||
(** {2 Arrays} *)
|
(** {2 Arrays} *)
|
||||||
|
|
||||||
|
(**/**)
|
||||||
|
external make_float : int -> float array = "caml_make_float_vect" (* compat *)
|
||||||
|
(**/**)
|
||||||
|
|
||||||
include module type of Array
|
include module type of Array
|
||||||
|
|
||||||
type 'a t = 'a array
|
type 'a t = 'a array
|
||||||
|
|
@ -57,28 +62,30 @@ val length : _ t -> int
|
||||||
(** [length a] returns the length (number of elements) of the given array [a]. *)
|
(** [length a] returns the length (number of elements) of the given array [a]. *)
|
||||||
|
|
||||||
val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
|
val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
|
||||||
(** [fold f acc a] computes [f (... (f (f acc a.(0)) a.(1)) ...) a.(n-1)],
|
(** [fold f init a] computes [f (... (f (f init a.(0)) a.(1)) ...) a.(n-1)],
|
||||||
where [n] is the length of the array [a]. *)
|
where [n] is the length of the array [a]. *)
|
||||||
|
|
||||||
val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
|
val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
|
||||||
(** [foldi f acc a] is just like {!fold}, but it also passes in the index
|
(** [foldi f init a] is just like {!fold}, but it also passes in the index
|
||||||
of each element as the second argument to the folded function [f]. *)
|
of each element as the second argument to the folded function [f]. *)
|
||||||
|
|
||||||
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
|
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
|
||||||
(** [fold_while f acc a] folds left on array [a] until a stop condition via [('a, `Stop)]
|
(** [fold_while f init a] folds left on array [a] until a stop condition via [('a, `Stop)]
|
||||||
is indicated by the accumulator.
|
is indicated by the accumulator.
|
||||||
@since 0.8 *)
|
@since 0.8 *)
|
||||||
|
|
||||||
val fold_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a t -> 'acc * 'b t
|
val fold_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a t -> 'acc * 'b t
|
||||||
(** [fold_map f acc a] is a [fold_left]-like function, but it also maps the
|
(** [fold_map f init a] is a [fold_left]-like function, but it also maps the
|
||||||
array to another array.
|
array to another array.
|
||||||
@since 1.2 *)
|
@since 1.2, but only
|
||||||
|
@since 2.1 with labels *)
|
||||||
|
|
||||||
val scan_left : ('acc -> 'a -> 'acc) -> 'acc -> 'a t -> 'acc t
|
val scan_left : ('acc -> 'a -> 'acc) -> 'acc -> 'a t -> 'acc t
|
||||||
(** [scan_left f acc a] returns the array
|
(** [scan_left f init a] returns the array
|
||||||
[ [|acc; f acc x0; f (f acc a.(0)) a.(1); …|] ].
|
[ [|init; f init x0; f (f init a.(0)) a.(1); …|] ].
|
||||||
|
|
||||||
@since 1.2 *)
|
@since 1.2, but only
|
||||||
|
@since 2.1 with labels *)
|
||||||
|
|
||||||
val iter : ('a -> unit) -> 'a t -> unit
|
val iter : ('a -> unit) -> 'a t -> unit
|
||||||
(** [iter f a] applies function [f] in turn to all elements of [a].
|
(** [iter f a] applies function [f] in turn to all elements of [a].
|
||||||
|
|
@ -103,24 +110,27 @@ val reverse_in_place : 'a t -> unit
|
||||||
(** [reverse_in_place a] reverses the array [a] in place. *)
|
(** [reverse_in_place a] reverses the array [a] in place. *)
|
||||||
|
|
||||||
val sorted : ('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].
|
(* FIXME: better label this ~cmp ?? *)
|
||||||
|
(** [sorted f a] makes a copy of [a] and sorts it with [f].
|
||||||
@since 1.0 *)
|
@since 1.0 *)
|
||||||
|
|
||||||
val sort_indices : ('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],
|
(* FIXME: better label this ~cmp ?? *)
|
||||||
such that [b.(i)] is the index at which the [i]-th element of [sorted cmp a]
|
(** [sort_indices f a] returns a new array [b], with the same length as [a],
|
||||||
|
such that [b.(i)] is the index at which the [i]-th element of [sorted f a]
|
||||||
appears in [a]. [a] is not modified.
|
appears in [a]. [a] is not modified.
|
||||||
|
|
||||||
In other words, [map (fun i -> a.(i)) (sort_indices cmp a) = sorted cmp a].
|
In other words, [map (fun i -> a.(i)) (sort_indices f a) = sorted f a].
|
||||||
[sort_indices] yields the inverse permutation of {!sort_ranking}.
|
[sort_indices] yields the inverse permutation of {!sort_ranking}.
|
||||||
@since 1.0 *)
|
@since 1.0 *)
|
||||||
|
|
||||||
val sort_ranking : ('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],
|
(* FIXME: better label this ~cmp ?? *)
|
||||||
|
(** [sort_ranking f a] returns a new array [b], with the same length as [a],
|
||||||
such that [b.(i)] is the index at which the [i]-th element of [a] appears
|
such that [b.(i)] is the index at which the [i]-th element of [a] appears
|
||||||
in [sorted cmp a]. [a] is not modified.
|
in [sorted f a]. [a] is not modified.
|
||||||
|
|
||||||
In other words, [map (fun i -> (sorted cmp a).(i)) (sort_ranking cmp a) = a].
|
In other words, [map (fun i -> (sorted f a).(i)) (sort_ranking f a) = a].
|
||||||
[sort_ranking] yields the inverse permutation of {!sort_indices}.
|
[sort_ranking] yields the inverse permutation of {!sort_indices}.
|
||||||
|
|
||||||
In the absence of duplicate elements in [a], we also have
|
In the absence of duplicate elements in [a], we also have
|
||||||
|
|
@ -130,97 +140,103 @@ val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array
|
||||||
val find_map : ('a -> 'b option) -> 'a t -> 'b option
|
val find_map : ('a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [find_map f a] returns [Some y] if there is an element [x] such
|
(** [find_map f a] returns [Some y] if there is an element [x] such
|
||||||
that [f x = Some y]. Otherwise returns [None].
|
that [f x = Some y]. Otherwise returns [None].
|
||||||
@since 1.3 *)
|
@since 1.3, but only
|
||||||
|
@since 2.1 with labels *)
|
||||||
|
|
||||||
val find : ('a -> 'b option) -> 'a t -> 'b option
|
val find : ('a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [find f a] is an alias to {!find_map}.
|
(** [find f a] is an alias to {!find_map}.
|
||||||
@deprecated since 1.3, use {!find_map} instead. *)
|
@deprecated since 1.3, use {!find_map} instead.
|
||||||
|
The version with labels is
|
||||||
|
@deprecated since 2.1, use {!find_map} instead. *)
|
||||||
|
|
||||||
val find_map_i : (int -> 'a -> 'b option) -> 'a t -> 'b option
|
val find_map_i : (int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [find_map_i f a] is like {!find_map}, but the index of the element is also passed
|
(** [find_map_i f a] is like {!find_map}, but the index of the element is also passed
|
||||||
to the predicate function [f].
|
to the predicate function [f].
|
||||||
@since 1.3 *)
|
@since 1.3, but only
|
||||||
|
@since 2.1 with labels *)
|
||||||
|
|
||||||
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
|
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [findi f a] is an alias to {!find_map_i}.
|
(** [findi f a] is an alias to {!find_map_i}.
|
||||||
@since 0.3.4
|
@since 0.3.4
|
||||||
@deprecated since 1.3, use {!find_map_i} instead. *)
|
@deprecated since 1.3, use {!find_map} instead.
|
||||||
|
The version with labels is
|
||||||
|
@deprecated since 2.1, use {!find_map} instead. *)
|
||||||
|
|
||||||
val find_idx : ('a -> bool) -> 'a t -> (int * 'a) option
|
val find_idx : ('a -> bool) -> 'a t -> (int * 'a) option
|
||||||
(** [find_idx p a] returns [Some (i,x)] where [x] is the [i]-th element of [a],
|
(** [find_idx f a] returns [Some (i,x)] where [x] is the [i]-th element of [a],
|
||||||
and [p x] holds. Otherwise returns [None].
|
and [f x] holds. Otherwise returns [None].
|
||||||
@since 0.3.4 *)
|
@since 0.3.4 *)
|
||||||
|
|
||||||
val lookup : cmp:'a ord -> 'a -> 'a t -> int option
|
val lookup : cmp:'a ord -> 'a -> 'a t -> int option
|
||||||
(** [lookup cmp x a] lookups the index of some key [x] in a sorted array [a].
|
(** [lookup ~cmp key a] lookups the index of some key [key] in a sorted array [a].
|
||||||
Undefined behavior if the array [a] is not sorted wrt [cmp].
|
Undefined behavior if the array [a] is not sorted wrt [~cmp].
|
||||||
Complexity: [O(log (n))] (dichotomic search).
|
Complexity: [O(log (n))] (dichotomic search).
|
||||||
@return [None] if the key [x] is not present, or
|
@return [None] if the key [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 -> 'a -> 'a t -> int
|
val lookup_exn : cmp:'a ord -> 'a -> 'a t -> int
|
||||||
(** [lookup_exn cmp x a] is like {!lookup}, but
|
(** [lookup_exn ~cmp key a] is like {!lookup}, but
|
||||||
@raise Not_found if the key [x] is not present. *)
|
@raise Not_found if the key [key] is not present. *)
|
||||||
|
|
||||||
val bsearch : cmp:('a -> 'a -> int) -> '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 x a] finds the index of the object [x] in the array [a],
|
(** [bsearch ~cmp key a] finds the index of the object [key] in the array [a],
|
||||||
provided [a] is {b sorted} using [cmp]. If the array is not sorted,
|
provided [a] 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).
|
||||||
|
|
||||||
Complexity: [O(log n)] where n is the length of the array [a]
|
Complexity: [O(log n)] where n is the length of the array [a]
|
||||||
(dichotomic search).
|
(dichotomic search).
|
||||||
|
|
||||||
@return
|
@return
|
||||||
- [`At i] if [cmp a.(i) x = 0] (for some i).
|
- [`At i] if [cmp a.(i) key = 0] (for some i).
|
||||||
- [`All_lower] if all elements of [a] are lower than [x].
|
- [`All_lower] if all elements of [a] are lower than [key].
|
||||||
- [`All_bigger] if all elements of [a] are bigger than [x].
|
- [`All_bigger] if all elements of [a] are bigger than [key].
|
||||||
- [`Just_after i] if [a.(i) < x < a.(i+1)].
|
- [`Just_after i] if [a.(i) < key < a.(i+1)].
|
||||||
- [`Empty] if the array [a] is empty.
|
- [`Empty] if the array [a] 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 : ('a -> bool) -> 'a t -> bool
|
val for_all : ('a -> bool) -> 'a t -> bool
|
||||||
(** [for_all p [|a1; ...; an|]] is [true] if all elements of the array
|
(** [for_all f [|a1; ...; an|]] is [true] if all elements of the array
|
||||||
satisfy the predicate [p]. That is, it returns
|
satisfy the predicate [f]. That is, it returns
|
||||||
[(p a1) && (p a2) && ... && (p an)]. *)
|
[(f a1) && (f a2) && ... && (f an)]. *)
|
||||||
|
|
||||||
val for_all2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
val for_all2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
||||||
(** [for_all2 p [|a1; ...; an|] [|b1; ...; bn|]] is [true] if each pair of elements [ai bi]
|
(** [for_all2 f [|a1; ...; an|] [|b1; ...; bn|]] is [true] if each pair of elements [ai bi]
|
||||||
satisfies the predicate [p].
|
satisfies the predicate [f].
|
||||||
That is, it returns [(p a1 b1) && (p a2 b2) && ... && (p an bn)].
|
That is, it returns [(f a1 b1) && (f a2 b2) && ... && (f an bn)].
|
||||||
|
|
||||||
@raise Invalid_argument if arrays have distinct lengths.
|
@raise Invalid_argument if arrays have distinct lengths.
|
||||||
Allow different types.
|
Allow different types.
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
||||||
val exists : ('a -> bool) -> 'a t -> bool
|
val exists : ('a -> bool) -> 'a t -> bool
|
||||||
(** [exists p [|a1; ...; an|]] is [true] if at least one element of
|
(** [exists f [|a1; ...; an|]] is [true] if at least one element of
|
||||||
the array satisfies the predicate [p]. That is, it returns
|
the array satisfies the predicate [f]. That is, it returns
|
||||||
[(p a1) || (p a2) || ... || (p an)]. *)
|
[(f a1) || (f a2) || ... || (f an)]. *)
|
||||||
|
|
||||||
val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
||||||
(** [exists2 p [|a1; ...; an|] [|b1; ...; bn|]] is [true] if any pair of elements [ai bi]
|
(** [exists2 f [|a1; ...; an|] [|b1; ...; bn|]] is [true] if any pair of elements [ai bi]
|
||||||
satisfies the predicate [p].
|
satisfies the predicate [f].
|
||||||
That is, it returns [(p a1 b1) || (p a2 b2) || ... || (p an bn)].
|
That is, it returns [(f a1 b1) || (f a2 b2) || ... || (f an bn)].
|
||||||
|
|
||||||
@raise Invalid_argument if arrays have distinct lengths.
|
@raise Invalid_argument if arrays have distinct lengths.
|
||||||
Allow different types.
|
Allow different types.
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
||||||
val fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc
|
val fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc
|
||||||
(** [fold2 f acc a b] fold on two arrays [a] and [b] stepwise.
|
(** [fold2 f init a b] fold on two arrays [a] and [b] stepwise.
|
||||||
It computes [f (... (f acc a1 b1)...) an bn].
|
It computes [f (... (f init a1 b1)...) an bn].
|
||||||
|
|
||||||
@raise Invalid_argument if arrays have distinct lengths.
|
@raise Invalid_argument if [a] and [b] have distinct lengths.
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
||||||
val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
||||||
(** [iter2 f a b] iterates on the two arrays [a] and [b] stepwise.
|
(** [iter2 f a b] iterates on the two arrays [a] and [b] stepwise.
|
||||||
It is equivalent to [f a0 b0; ...; f a.(length a - 1) b.(length b - 1); ()].
|
It is equivalent to [f a0 b0; ...; f a.(length a - 1) b.(length b - 1); ()].
|
||||||
|
|
||||||
@raise Invalid_argument if arrays have distinct lengths.
|
@raise Invalid_argument if [a] and [b] have distinct lengths.
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
||||||
val shuffle : 'a t -> unit
|
val shuffle : 'a t -> unit
|
||||||
|
|
@ -275,8 +291,8 @@ val rev : 'a t -> 'a t
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
||||||
val filter : ('a -> bool) -> 'a t -> 'a t
|
val filter : ('a -> bool) -> 'a t -> 'a t
|
||||||
(** [filter p a] filters elements out of the array [a]. Only the elements satisfying
|
(** [filter f a] filters elements out of the array [a]. Only the elements satisfying
|
||||||
the given predicate [p] will be kept. *)
|
the given predicate [f] will be kept. *)
|
||||||
|
|
||||||
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
|
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
|
||||||
(** [filter_map f [|a1; ...; an|]] calls [(f a1) ... (f an)] and returns an array [b] consisting
|
(** [filter_map f [|a1; ...; an|]] calls [(f a1) ... (f an)] and returns an array [b] consisting
|
||||||
|
|
@ -328,6 +344,6 @@ end
|
||||||
val sort_generic :
|
val sort_generic :
|
||||||
(module MONO_ARRAY with type t = 'arr and type elt = 'elt) ->
|
(module MONO_ARRAY with type t = 'arr and type elt = 'elt) ->
|
||||||
cmp:('elt -> 'elt -> int) -> 'arr -> unit
|
cmp:('elt -> 'elt -> int) -> 'arr -> unit
|
||||||
(** [sort_generic (module M) cmp a] sorts the array [a], without allocating (eats stack space though).
|
(** [sort_generic (module M) ~cmp a] sorts the array [a], without allocating (eats stack space though).
|
||||||
Performance might be lower than {!Array.sort}.
|
Performance might be lower than {!Array.sort}.
|
||||||
@since 0.14 *)
|
@since 0.14 *)
|
||||||
|
|
|
||||||
|
|
@ -75,13 +75,15 @@ val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t ->
|
||||||
val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a t -> 'acc * 'b t
|
val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a t -> 'acc * 'b t
|
||||||
(** [fold_map ~f ~init a] is a [fold_left]-like function, but it also maps the
|
(** [fold_map ~f ~init a] is a [fold_left]-like function, but it also maps the
|
||||||
array to another array.
|
array to another array.
|
||||||
@since 2.1 *)
|
@since 1.2, but only
|
||||||
|
@since 2.1 with labels *)
|
||||||
|
|
||||||
val scan_left : f:('acc -> 'a -> 'acc) -> init:'acc -> 'a t -> 'acc t
|
val scan_left : f:('acc -> 'a -> 'acc) -> init:'acc -> 'a t -> 'acc t
|
||||||
(** [scan_left ~f ~init a] returns the array
|
(** [scan_left ~f ~init a] returns the array
|
||||||
[ [|~init; ~f ~init x0; ~f (~f ~init a.(0)) a.(1); …|] ].
|
[ [|~init; ~f ~init x0; ~f (~f ~init a.(0)) a.(1); …|] ].
|
||||||
|
|
||||||
@since 2.1 *)
|
@since 1.2, but only
|
||||||
|
@since 2.1 with labels *)
|
||||||
|
|
||||||
val iter : f:('a -> unit) -> 'a t -> unit
|
val iter : f:('a -> unit) -> 'a t -> unit
|
||||||
(** [iter ~f a] applies function [~f] in turn to all elements of [a].
|
(** [iter ~f a] applies function [~f] in turn to all elements of [a].
|
||||||
|
|
@ -106,10 +108,12 @@ val reverse_in_place : 'a t -> unit
|
||||||
(** [reverse_in_place a] reverses the array [a] in place. *)
|
(** [reverse_in_place a] reverses the array [a] in place. *)
|
||||||
|
|
||||||
val sorted : f:('a -> 'a -> int) -> 'a t -> 'a array
|
val sorted : f:('a -> 'a -> int) -> 'a t -> 'a array
|
||||||
|
(* FIXME: better label this ~cmp ?? *)
|
||||||
(** [sorted ~f a] makes a copy of [a] and sorts it with [~f].
|
(** [sorted ~f a] makes a copy of [a] and sorts it with [~f].
|
||||||
@since 1.0 *)
|
@since 1.0 *)
|
||||||
|
|
||||||
val sort_indices : f:('a -> 'a -> int) -> 'a t -> int array
|
val sort_indices : f:('a -> 'a -> int) -> 'a t -> int array
|
||||||
|
(* FIXME: better label this ~cmp ?? *)
|
||||||
(** [sort_indices ~f a] returns a new array [b], with the same length as [a],
|
(** [sort_indices ~f a] returns a new array [b], with the same length as [a],
|
||||||
such that [b.(i)] is the index at which the [i]-th element of [sorted ~f a]
|
such that [b.(i)] is the index at which the [i]-th element of [sorted ~f a]
|
||||||
appears in [a]. [a] is not modified.
|
appears in [a]. [a] is not modified.
|
||||||
|
|
@ -119,6 +123,7 @@ val sort_indices : f:('a -> 'a -> int) -> 'a t -> int array
|
||||||
@since 1.0 *)
|
@since 1.0 *)
|
||||||
|
|
||||||
val sort_ranking : f:('a -> 'a -> int) -> 'a t -> int array
|
val sort_ranking : f:('a -> 'a -> int) -> 'a t -> int array
|
||||||
|
(* FIXME: better label this ~cmp ?? *)
|
||||||
(** [sort_ranking ~f a] returns a new array [b], with the same length as [a],
|
(** [sort_ranking ~f a] returns a new array [b], with the same length as [a],
|
||||||
such that [b.(i)] is the index at which the [i]-th element of [a] appears
|
such that [b.(i)] is the index at which the [i]-th element of [a] appears
|
||||||
in [sorted ~f a]. [a] is not modified.
|
in [sorted ~f a]. [a] is not modified.
|
||||||
|
|
@ -133,39 +138,45 @@ val sort_ranking : f:('a -> 'a -> int) -> 'a t -> int array
|
||||||
val find_map : f:('a -> 'b option) -> 'a t -> 'b option
|
val find_map : f:('a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [find_map ~f a] returns [Some y] if there is an element [x] such
|
(** [find_map ~f a] returns [Some y] if there is an element [x] such
|
||||||
that [~f x = Some y]. Otherwise returns [None].
|
that [~f x = Some y]. Otherwise returns [None].
|
||||||
@since 2.1 *)
|
@since 1.3, but only
|
||||||
|
@since 2.1 with labels *)
|
||||||
|
|
||||||
val find : f:('a -> 'b option) -> 'a t -> 'b option
|
val find : f:('a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [find ~f a] is an alias to {!find_map}.
|
(** [find ~f a] is an alias to {!find_map}.
|
||||||
|
@deprecated since 1.3, use {!find_map} instead.
|
||||||
|
The version with labels is
|
||||||
@deprecated since 2.1, use {!find_map} instead. *)
|
@deprecated since 2.1, use {!find_map} instead. *)
|
||||||
|
|
||||||
val find_map_i : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
val find_map_i : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [find_map_i ~f a] is like {!find_map}, but the index of the element is also passed
|
(** [find_map_i ~f a] is like {!find_map}, but the index of the element is also passed
|
||||||
to the predicate function [~f].
|
to the predicate function [~f].
|
||||||
@since 2.1 *)
|
@since 1.3, but only
|
||||||
|
@since 2.1 with labels *)
|
||||||
|
|
||||||
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [findi ~f a] is an alias to {!find_map_i}.
|
(** [findi ~f a] is an alias to {!find_map_i}.
|
||||||
@since 0.3.4
|
@since 0.3.4
|
||||||
@deprecated since 2.1, use {!find_map_i} instead. *)
|
@deprecated since 1.3, use {!find_map} instead.
|
||||||
|
The version with labels is
|
||||||
|
@deprecated since 2.1, use {!find_map} instead. *)
|
||||||
|
|
||||||
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option
|
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option
|
||||||
(** [find_idx ~f a] returns [Some (i,x)] where [x] is the [i]-th element of [a],
|
(** [find_idx ~f a] returns [Some (i,x)] where [x] is the [i]-th element of [a],
|
||||||
and [~f x] holds. Otherwise returns [None].
|
and [~f 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 [@keep_label]) -> key:'a -> 'a t -> int option
|
||||||
(** [lookup ~cmp ~key a] lookups the index of some key [~key] in a sorted array [a].
|
(** [lookup ~cmp ~key a] lookups the index of some key [~key] in a sorted array [a].
|
||||||
Undefined behavior if the array [a] is not sorted wrt [~cmp].
|
Undefined behavior if the array [a] is not sorted wrt [~cmp].
|
||||||
Complexity: [O(log (n))] (dichotomic search).
|
Complexity: [O(log (n))] (dichotomic search).
|
||||||
@return [None] if the key [~key] is not present, or
|
@return [None] if the key [~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 [@keep_label]) -> key:'a -> 'a t -> int
|
||||||
(** [lookup_exn ~cmp ~key a] is like {!lookup}, but
|
(** [lookup_exn ~cmp ~key a] is like {!lookup}, but
|
||||||
@raise Not_found if the key [~key] is not present. *)
|
@raise Not_found if the key [~key] is not present. *)
|
||||||
|
|
||||||
val bsearch : cmp:('a -> 'a -> int) -> key:'a -> 'a t ->
|
val bsearch : cmp:(('a -> 'a -> int) [@keep_label]) -> key:'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 a] finds the index of the object [~key] in the array [a],
|
(** [bsearch ~cmp ~key a] finds the index of the object [~key] in the array [a],
|
||||||
provided [a] is {b sorted} using [~cmp]. If the array is not sorted,
|
provided [a] is {b sorted} using [~cmp]. If the array is not sorted,
|
||||||
|
|
@ -270,8 +281,8 @@ val map2 : f:('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
||||||
and builds an array with the results returned by [~f]:
|
and builds an array with the results returned by [~f]:
|
||||||
[[| ~f a.(0) b.(0); ...; ~f a.(length a - 1) b.(length b - 1)|]].
|
[[| ~f a.(0) b.(0); ...; ~f a.(length a - 1) b.(length b - 1)|]].
|
||||||
|
|
||||||
@raise Invalid_argument if [a] and [b] have distinct lengths.
|
@raise Invalid_argument if [a] and [b] have distinct lengths.
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
||||||
val rev : 'a t -> 'a t
|
val rev : 'a t -> 'a t
|
||||||
(** [rev a] copies the array [a] and reverses it in place.
|
(** [rev a] copies the array [a] and reverses it in place.
|
||||||
|
|
@ -330,8 +341,7 @@ end
|
||||||
|
|
||||||
val sort_generic :
|
val sort_generic :
|
||||||
(module MONO_ARRAY with type t = 'arr and type elt = 'elt) ->
|
(module MONO_ARRAY with type t = 'arr and type elt = 'elt) ->
|
||||||
cmp:('elt -> 'elt -> int) -> 'arr -> unit
|
cmp:(('elt -> 'elt -> int) [@keep_label]) -> 'arr -> unit
|
||||||
(** [sort_generic (module M) ~cmp a] sorts the array [a], without allocating (eats stack space though).
|
(** [sort_generic (module M) ~cmp a] sorts the array [a], without allocating (eats stack space though).
|
||||||
Performance might be lower than {!Array.sort}.
|
Performance might be lower than {!Array.sort}.
|
||||||
@since 0.14 *)
|
@since 0.14 *)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -968,7 +968,7 @@ let find_idx p l = find_mapi (fun i x -> if p x then Some (i, x) else None) l
|
||||||
find_map (fun x -> if x=3 then Some "a" else None) [1;2;4;5] = None
|
find_map (fun x -> if x=3 then Some "a" else None) [1;2;4;5] = None
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let remove ~eq ~x 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
|
||||||
|
|
@ -977,8 +977,8 @@ let remove ~eq ~x l =
|
||||||
remove' eq x [] l
|
remove' eq x [] l
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
remove ~eq:CCInt.equal ~x:1 [2;1;3;3;2;1] = [2;3;3;2]
|
remove ~eq:CCInt.equal 1 [2;1;3;3;2;1] = [2;3;3;2]
|
||||||
remove ~eq:CCInt.equal ~x:10 [1;2;3] = [1;2;3]
|
remove ~eq:CCInt.equal 10 [1;2;3] = [1;2;3]
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let filter_map f l =
|
let filter_map f l =
|
||||||
|
|
@ -1483,7 +1483,7 @@ module Assoc = struct
|
||||||
not (Assoc.mem ~eq:CCInt.equal 4 [1,"1"; 2,"2"; 3, "3"])
|
not (Assoc.mem ~eq:CCInt.equal 4 [1,"1"; 2,"2"; 3, "3"])
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let update ~eq ~f x l =
|
let update ~eq f x l =
|
||||||
search_set eq [] l x
|
search_set eq [] l x
|
||||||
~f:(fun x opt_y rest ->
|
~f:(fun x opt_y rest ->
|
||||||
match f opt_y with
|
match f opt_y with
|
||||||
|
|
@ -1492,13 +1492,13 @@ module Assoc = struct
|
||||||
(*$=
|
(*$=
|
||||||
[1,"1"; 2,"22"] \
|
[1,"1"; 2,"22"] \
|
||||||
(Assoc.update ~eq:CCInt.equal \
|
(Assoc.update ~eq:CCInt.equal \
|
||||||
~f:(function Some "2" -> Some "22" | _ -> assert false) 2 [1,"1"; 2,"2"] |> lsort)
|
(function Some "2" -> Some "22" | _ -> assert false) 2 [1,"1"; 2,"2"] |> lsort)
|
||||||
[1,"1"; 3,"3"] \
|
[1,"1"; 3,"3"] \
|
||||||
(Assoc.update ~eq:CCInt.equal \
|
(Assoc.update ~eq:CCInt.equal \
|
||||||
~f:(function Some "2" -> None | _ -> assert false) 2 [1,"1"; 2,"2"; 3,"3"] |> lsort)
|
(function Some "2" -> None | _ -> assert false) 2 [1,"1"; 2,"2"; 3,"3"] |> lsort)
|
||||||
[1,"1"; 2,"2"; 3,"3"] \
|
[1,"1"; 2,"2"; 3,"3"] \
|
||||||
(Assoc.update ~eq:CCInt.equal \
|
(Assoc.update ~eq:CCInt.equal \
|
||||||
~f:(function None -> Some "3" | _ -> assert false) 3 [1,"1"; 2,"2"] |> lsort)
|
(function None -> Some "3" | _ -> assert false) 3 [1,"1"; 2,"2"] |> lsort)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let remove ~eq x l =
|
let remove ~eq x l =
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
(* AUTOGENERATED FROM CCListLabels.mli *)
|
||||||
|
|
||||||
|
|
||||||
(* 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. *)
|
||||||
|
|
||||||
|
|
@ -61,14 +63,15 @@ val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
|
||||||
@since 0.8 *)
|
@since 0.8 *)
|
||||||
|
|
||||||
val fold_map : ('acc -> 'a -> 'acc * 'b) -> '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 init 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 scan_left : ('acc -> 'a -> 'acc) -> 'acc -> 'a list -> 'acc list
|
val scan_left : ('acc -> 'a -> 'acc) -> 'acc -> 'a list -> 'acc list
|
||||||
(** [scan_left f acc l] returns the list [[acc; f acc x0; f (f acc x0) x1; ...]]
|
(** [scan_left f init l] returns the list [[init; f init x0; f (f init x0) x1; ...]]
|
||||||
where [x0], [x1], etc. are the elements of [l].
|
where [x0], [x1], etc. are the elements of [l].
|
||||||
@since 1.2 *)
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val fold_map2 : ('acc -> 'a -> 'b -> 'acc * 'c) -> '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].
|
||||||
|
|
@ -76,7 +79,7 @@ val fold_map2 : ('acc -> 'a -> 'b -> 'acc * 'c) -> 'acc -> 'a list -> 'b list ->
|
||||||
@since 0.16 *)
|
@since 0.16 *)
|
||||||
|
|
||||||
val fold_filter_map : ('acc -> 'a -> 'acc * 'b option) -> '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 init 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 *)
|
||||||
|
|
||||||
|
|
@ -87,12 +90,11 @@ val fold_flat_map : ('acc -> 'a -> 'acc * 'b list) -> 'acc -> 'a list -> 'acc *
|
||||||
|
|
||||||
val count : ('a -> bool) -> 'a list -> int
|
val count : ('a -> bool) -> 'a list -> int
|
||||||
(** [count p l] counts how many elements of [l] satisfy predicate [p].
|
(** [count p l] counts how many elements of [l] satisfy predicate [p].
|
||||||
@since 1.5 *)
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val count_true_false : ('a -> bool) -> 'a list -> int * int
|
val count_true_false : ('a -> bool) -> 'a list -> int * int
|
||||||
(** [let ok_count, ko_count = count_true_false p l in ...]
|
(** @since NEXT_RELEASE *)
|
||||||
count_true_false how many elements of [l] satisfy (resp. violate) predicate [p].
|
|
||||||
@since NEXT_RELEASE *)
|
|
||||||
|
|
||||||
val init : int -> (int -> 'a) -> 'a t
|
val init : int -> (int -> 'a) -> 'a t
|
||||||
(** [init len f] is [f 0; f 1; ...; f (len-1)].
|
(** [init len f] is [f 0; f 1; ...; f (len-1)].
|
||||||
|
|
@ -105,31 +107,37 @@ val combine : 'a list -> 'b list -> ('a * 'b) list
|
||||||
[combine [a1; ...; an] [b1; ...; bn]] is
|
[combine [a1; ...; an] [b1; ...; bn]] is
|
||||||
[[(a1,b1); ...; (an,bn)]].
|
[[(a1,b1); ...; (an,bn)]].
|
||||||
@raise Invalid_argument if the lists have distinct lengths.
|
@raise Invalid_argument if the lists have distinct lengths.
|
||||||
@since 1.2 *)
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val combine_gen : 'a list -> 'b list -> ('a * 'b) gen
|
val combine_gen : 'a list -> 'b list -> ('a * 'b) gen
|
||||||
(** Lazy version of {!combine}.
|
(** Lazy version of {!combine}.
|
||||||
Unlike {!combine}, it does not fail if the lists have different
|
Unlike {!combine}, it does not fail if the lists have different
|
||||||
lengths;
|
lengths;
|
||||||
instead, the output has as many pairs as the smallest input list.
|
instead, the output has as many pairs as the smallest input list.
|
||||||
@since 1.2 *)
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val split : ('a * 'b) t -> 'a t * 'b t
|
val split : ('a * 'b) t -> 'a t * 'b t
|
||||||
(** A tail-recursive version of {!List.split}.
|
(** A tail-recursive version of {!List.split}.
|
||||||
Transform a list of pairs into a pair of lists:
|
Transform a list of pairs into a pair of lists:
|
||||||
[split [(a1,b1); ...; (an,bn)]] is [([a1; ...; an], [b1; ...; bn])]. *)
|
[split [(a1,b1); ...; (an,bn)]] is [([a1; ...; an], [b1; ...; bn])].
|
||||||
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
|
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
|
||||||
|
|
||||||
val compare_lengths : 'a t -> 'b t -> int
|
val compare_lengths : 'a t -> 'b t -> int
|
||||||
(** Equivalent to [compare (length l1) (length l2)] but more efficient.
|
(** Equivalent to [compare (length l1) (length l2)] but more efficient.
|
||||||
Compare the lengths of two lists.
|
Compare the lengths of two lists.
|
||||||
@since 1.5 *)
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val compare_length_with : 'a t -> int -> int
|
val compare_length_with : 'a t -> int -> int
|
||||||
(** Equivalent to [compare (length l) x] but more efficient.
|
(** Equivalent to [compare (length l) x] but more efficient.
|
||||||
Compare the length of a list to an integer.
|
Compare the length of a list to an integer.
|
||||||
@since 1.5 *)
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
||||||
|
|
||||||
|
|
@ -158,14 +166,16 @@ val cartesian_product : 'a t t -> 'a t t
|
||||||
[[1;3;4;5;6];[2;3;4;5;6]];;
|
[[1;3;4;5;6];[2;3;4;5;6]];;
|
||||||
]}
|
]}
|
||||||
invariant: [cartesian_product l = map_product id l].
|
invariant: [cartesian_product l = map_product id l].
|
||||||
@since 1.2 *)
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val map_product_l : ('a -> 'b list) -> 'a list -> 'b list list
|
val map_product_l : ('a -> 'b list) -> 'a list -> 'b list list
|
||||||
(** [map_product_l f l] maps each element of [l] to a list of
|
(** [map_product_l f l] maps each element of [l] to a list of
|
||||||
objects of type ['b] using [f].
|
objects of type ['b] using [f].
|
||||||
We obtain [[l1;l2;...;ln]] where [length l=n] and [li : 'b list].
|
We obtain [[l1;l2;...;ln]] where [length l=n] and [li : 'b list].
|
||||||
Then, it returns all the ways of picking exactly one element per [li].
|
Then, it returns all the ways of picking exactly one element per [li].
|
||||||
@since 1.2 *)
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -263,16 +273,21 @@ val sublists_of_len :
|
||||||
If [last = CCOpt.return], it will simply keep the last group.
|
If [last = CCOpt.return], it will simply keep the last group.
|
||||||
By default, [last = fun _ -> None], i.e. the last group is dropped if shorter than [n].
|
By default, [last = fun _ -> None], i.e. the last group is dropped if shorter than [n].
|
||||||
@raise Invalid_argument if [offset <= 0] or [n <= 0].
|
@raise Invalid_argument if [offset <= 0] or [n <= 0].
|
||||||
@since 1.0 *)
|
See {!CCList.sublists_of_len} for more details.
|
||||||
|
|
||||||
|
@since 1.0, but only
|
||||||
|
@since 1.5 with labels *)
|
||||||
|
|
||||||
val intersperse : 'a -> 'a list -> 'a list
|
val intersperse : 'a -> 'a list -> 'a list
|
||||||
(** Insert the first argument between every element of the list.
|
(** Insert the first argument between every element of the list.
|
||||||
@since 2.1 *)
|
@since 2.1, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val interleave : 'a list -> 'a list -> 'a list
|
val interleave : 'a list -> 'a list -> 'a list
|
||||||
(** [interleave [x1…xn] [y1…ym]] is [x1,y1,x2,y2,…] and finishes with
|
(** [interleave [x1…xn] [y1…ym]] is [x1,y1,x2,y2,…] and finishes with
|
||||||
the suffix of the longest list.
|
the suffix of the longest list.
|
||||||
@since 2.1 *)
|
@since 2.1, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val pure : 'a -> 'a t
|
val pure : 'a -> 'a t
|
||||||
(** [pure] is [return]. *)
|
(** [pure] is [return]. *)
|
||||||
|
|
@ -281,7 +296,7 @@ val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
||||||
(** [funs <*> l] is [product (fun f x -> f x) funs l]. *)
|
(** [funs <*> l] is [product (fun f x -> f x) funs l]. *)
|
||||||
|
|
||||||
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
|
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
|
||||||
(** [(<$>)] = [map]. *)
|
(** [(<$>)] is [map]. *)
|
||||||
|
|
||||||
val return : 'a -> 'a t
|
val return : 'a -> 'a t
|
||||||
(** [return x] is [x]. *)
|
(** [return x] is [x]. *)
|
||||||
|
|
@ -314,7 +329,8 @@ val drop_while : ('a -> bool) -> 'a t -> 'a t
|
||||||
|
|
||||||
val take_drop_while : ('a -> bool) -> 'a t -> 'a t * 'a t
|
val take_drop_while : ('a -> bool) -> 'a t -> 'a t * 'a t
|
||||||
(** [take_drop_while p l] = [take_while p l, drop_while p l].
|
(** [take_drop_while p l] = [take_while p l, drop_while p l].
|
||||||
@since 1.2 *)
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val last : int -> 'a t -> 'a t
|
val last : int -> 'a t -> 'a t
|
||||||
(** [last n l] takes the last [n] elements of [l] (or less if
|
(** [last n l] takes the last [n] elements of [l] (or less if
|
||||||
|
|
@ -339,7 +355,8 @@ val find_pred : ('a -> bool) -> 'a t -> 'a option
|
||||||
|
|
||||||
val find_opt : ('a -> bool) -> 'a t -> 'a option
|
val find_opt : ('a -> bool) -> 'a t -> 'a option
|
||||||
(** Safe version of {!find}.
|
(** Safe version of {!find}.
|
||||||
@since 1.5 *)
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val find_pred_exn : ('a -> bool) -> 'a t -> 'a
|
val find_pred_exn : ('a -> bool) -> 'a t -> 'a
|
||||||
(** Unsafe version of {!find_pred}.
|
(** Unsafe version of {!find_pred}.
|
||||||
|
|
@ -360,8 +377,9 @@ 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) -> x:'a -> 'a t -> 'a t
|
val remove : eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t
|
||||||
(** [remove ~x l] removes every instance of [x] from [l]. Tail-recursive.
|
(* FIXME: the original CCList.mli uses ~x instead of ~key !! *)
|
||||||
|
(** [remove key l] removes every instance of [key] from [l]. Tail-recursive.
|
||||||
@param eq equality function.
|
@param eq equality function.
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
|
|
@ -373,21 +391,25 @@ val filter_map : ('a -> 'b option) -> 'a t -> 'b t
|
||||||
val keep_some : 'a option t -> 'a t
|
val keep_some : 'a option t -> 'a t
|
||||||
(** [keep_some l] retains only elements of the form [Some x].
|
(** [keep_some l] retains only elements of the form [Some x].
|
||||||
Like [filter_map CCFun.id].
|
Like [filter_map CCFun.id].
|
||||||
@since 1.3 *)
|
@since 1.3, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val keep_ok : ('a, _) Result.result t -> 'a t
|
val keep_ok : ('a, _) Result.result t -> 'a t
|
||||||
(** [keep_ok l] retains only elements of the form [Ok x].
|
(** [keep_ok l] retains only elements of the form [Ok x].
|
||||||
@since 1.3 *)
|
@since 1.3, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val all_some : 'a option t -> 'a t option
|
val all_some : 'a option t -> 'a t option
|
||||||
(** [all_some l] returns [Some l'] if all elements of [l] are of the form [Some x],
|
(** [all_some l] returns [Some l'] if all elements of [l] are of the form [Some x],
|
||||||
or [None] otherwise.
|
or [None] otherwise.
|
||||||
@since 1.3 *)
|
@since 1.3, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val all_ok : ('a, 'err) Result.result t -> ('a t, 'err) Result.result
|
val all_ok : ('a, 'err) Result.result t -> ('a t, 'err) Result.result
|
||||||
(** [all_ok l] returns [Ok l'] if all elements of [l] are of the form [Ok x],
|
(** [all_ok l] returns [Ok l'] if all elements of [l] are of the form [Ok x],
|
||||||
or [Error e] otherwise (with the first error met).
|
or [Error e] otherwise (with the first error met).
|
||||||
@since 1.3 *)
|
@since 1.3, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
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
|
||||||
(** Merge elements from both sorted list. *)
|
(** Merge elements from both sorted list. *)
|
||||||
|
|
@ -439,7 +461,8 @@ val iteri : (int -> 'a -> unit) -> 'a t -> unit
|
||||||
val iteri2 : (int -> 'a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
val iteri2 : (int -> 'a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
||||||
(** Iter on two lists.
|
(** Iter on two lists.
|
||||||
@raise Invalid_argument when lists do not have the same length.
|
@raise Invalid_argument when lists do not have the same length.
|
||||||
@since 2.0 *)
|
@since 2.0, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
||||||
(** Like [fold] but it also passes in the index of each element to the folded function. Tail-recursive. *)
|
(** Like [fold] but it also passes in the index of each element to the folded function. Tail-recursive. *)
|
||||||
|
|
@ -447,7 +470,8 @@ val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
||||||
val foldi2 : ('c -> int -> 'a -> 'b -> 'c) -> 'c -> 'a t -> 'b t -> 'c
|
val foldi2 : ('c -> int -> 'a -> 'b -> 'c) -> 'c -> 'a t -> 'b t -> 'c
|
||||||
(** Fold on two lists, with index.
|
(** Fold on two lists, with index.
|
||||||
@raise Invalid_argument when lists do not have the same length.
|
@raise Invalid_argument when lists do not have the same length.
|
||||||
@since 2.0 *)
|
@since 2.0, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val get_at_idx : int -> 'a t -> 'a option
|
val get_at_idx : int -> 'a t -> 'a option
|
||||||
(** Get by index in the list.
|
(** Get by index in the list.
|
||||||
|
|
@ -457,7 +481,8 @@ val get_at_idx : int -> 'a t -> 'a option
|
||||||
val nth_opt : 'a t -> int -> 'a option
|
val nth_opt : 'a t -> int -> 'a option
|
||||||
(** Safe version of {!nth}.
|
(** Safe version of {!nth}.
|
||||||
@raise Invalid_argument if the int is negative.
|
@raise Invalid_argument if the int is negative.
|
||||||
@since 1.5 *)
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val get_at_idx_exn : int -> 'a t -> 'a
|
val get_at_idx_exn : int -> 'a t -> 'a
|
||||||
(** Get the i-th element, or
|
(** Get the i-th element, or
|
||||||
|
|
@ -564,8 +589,9 @@ module Assoc : sig
|
||||||
@since 0.16 *)
|
@since 0.16 *)
|
||||||
|
|
||||||
val update :
|
val update :
|
||||||
eq:('a->'a->bool) -> f:('b option -> 'b option) -> 'a -> ('a,'b) t -> ('a,'b) t
|
eq:('a->'a->bool) -> ('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)]
|
(* FIXME: the original no labels mli kept the ~f label ! *)
|
||||||
|
(** [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
|
and removing [k] if it returns [None], mapping [k] to [v'] if it
|
||||||
returns [Some v'].
|
returns [Some v'].
|
||||||
@since 0.16 *)
|
@since 0.16 *)
|
||||||
|
|
@ -581,11 +607,13 @@ val assoc : eq:('a -> 'a -> bool) -> 'a -> ('a * 'b) t -> 'b
|
||||||
|
|
||||||
val assoc_opt : eq:('a -> 'a -> bool) -> 'a -> ('a * 'b) t -> 'b option
|
val assoc_opt : eq:('a -> 'a -> bool) -> 'a -> ('a * 'b) t -> 'b option
|
||||||
(** Like [Assoc.get].
|
(** Like [Assoc.get].
|
||||||
@since 1.5 *)
|
@since 1.5, but only
|
||||||
|
@since 2.0 with labels *)
|
||||||
|
|
||||||
val assq_opt : 'a -> ('a * 'b) t -> 'b option
|
val assq_opt : 'a -> ('a * 'b) t -> 'b option
|
||||||
(** Safe version of {!assq}.
|
(** Safe version of {!assq}.
|
||||||
@since 1.5 *)
|
@since 1.5, but only
|
||||||
|
@since 2.0 with labels *)
|
||||||
|
|
||||||
val mem_assoc : eq:('a -> 'a -> bool) -> 'a -> ('a * _) t -> bool
|
val mem_assoc : eq:('a -> 'a -> bool) -> 'a -> ('a * _) t -> bool
|
||||||
(** Like [Assoc.mem].
|
(** Like [Assoc.mem].
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,10 @@ val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a list -> 'acc * 'b
|
||||||
@since 0.14 *)
|
@since 0.14 *)
|
||||||
|
|
||||||
val scan_left : f:('acc -> 'a -> 'acc) -> init:'acc -> 'a list -> 'acc list
|
val scan_left : f:('acc -> 'a -> 'acc) -> init:'acc -> 'a list -> 'acc list
|
||||||
(** @since 2.2 *)
|
(** [scan_left ~f ~init l] returns the list [[init; f init x0; f (f init x0) x1; ...]]
|
||||||
|
where [x0], [x1], etc. are the elements of [l].
|
||||||
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val fold_map2 : f:('acc -> 'a -> 'b -> 'acc * 'c) -> init:'acc -> 'a list -> 'b list -> 'acc * 'c list
|
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].
|
(** [fold_map2] is to [fold_map] what [List.map2] is to [List.map].
|
||||||
|
|
@ -84,7 +87,9 @@ val fold_flat_map : f:('acc -> 'a -> 'acc * 'b list) -> init:'acc -> 'a list ->
|
||||||
@since 0.14 *)
|
@since 0.14 *)
|
||||||
|
|
||||||
val count : f:('a -> bool) -> 'a list -> int
|
val count : f:('a -> bool) -> 'a list -> int
|
||||||
(** @since 2.2 *)
|
(** [count p l] counts how many elements of [l] satisfy predicate [p].
|
||||||
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val count_true_false : f:('a -> bool) -> 'a list -> int * int
|
val count_true_false : f:('a -> bool) -> 'a list -> int * int
|
||||||
(** @since NEXT_RELEASE *)
|
(** @since NEXT_RELEASE *)
|
||||||
|
|
@ -95,21 +100,42 @@ val init : int -> f:(int -> 'a) -> 'a t
|
||||||
@since 0.6 *)
|
@since 0.6 *)
|
||||||
|
|
||||||
val combine : 'a list -> 'b list -> ('a * 'b) list
|
val combine : 'a list -> 'b list -> ('a * 'b) list
|
||||||
(** @since 2.2 *)
|
(** Like {!List.combine} but tail-recursive.
|
||||||
|
Transform a pair of lists into a list of pairs:
|
||||||
|
[combine [a1; ...; an] [b1; ...; bn]] is
|
||||||
|
[[(a1,b1); ...; (an,bn)]].
|
||||||
|
@raise Invalid_argument if the lists have distinct lengths.
|
||||||
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val combine_gen : 'a list -> 'b list -> ('a * 'b) gen
|
val combine_gen : 'a list -> 'b list -> ('a * 'b) gen
|
||||||
(** @since 2.2 *)
|
(** Lazy version of {!combine}.
|
||||||
|
Unlike {!combine}, it does not fail if the lists have different
|
||||||
|
lengths;
|
||||||
|
instead, the output has as many pairs as the smallest input list.
|
||||||
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val split : ('a * 'b) t -> 'a t * 'b t
|
val split : ('a * 'b) t -> 'a t * 'b t
|
||||||
(** @since 2.2 *)
|
(** A tail-recursive version of {!List.split}.
|
||||||
|
Transform a list of pairs into a pair of lists:
|
||||||
|
[split [(a1,b1); ...; (an,bn)]] is [([a1; ...; an], [b1; ...; bn])].
|
||||||
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
|
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
|
||||||
|
|
||||||
val compare_lengths : 'a t -> 'b t -> int
|
val compare_lengths : 'a t -> 'b t -> int
|
||||||
(** @since 2.2 *)
|
(** Equivalent to [compare (length l1) (length l2)] but more efficient.
|
||||||
|
Compare the lengths of two lists.
|
||||||
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val compare_length_with : 'a t -> int -> int
|
val compare_length_with : 'a t -> int -> int
|
||||||
(** @since 2.2 *)
|
(** Equivalent to [compare (length l) x] but more efficient.
|
||||||
|
Compare the length of a list to an integer.
|
||||||
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
||||||
|
|
||||||
|
|
@ -126,10 +152,28 @@ val fold_product : f:('c -> 'a -> 'b -> 'c) -> init:'c -> 'a t -> 'b t -> 'c
|
||||||
(** Fold on the cartesian product. *)
|
(** Fold on the cartesian product. *)
|
||||||
|
|
||||||
val cartesian_product : 'a t t -> 'a t t
|
val cartesian_product : 'a t t -> 'a t t
|
||||||
(** @since 2.2 *)
|
(** Produce the cartesian product of this list of lists,
|
||||||
|
by returning all the ways of picking one element per sublist.
|
||||||
|
{b NOTE} the order of the returned list is unspecified.
|
||||||
|
For example:
|
||||||
|
{[
|
||||||
|
# cartesian_product [[1;2];[3];[4;5;6]] |> sort =
|
||||||
|
[[1;3;4];[1;3;5];[1;3;6];[2;3;4];[2;3;5];[2;3;6]];;
|
||||||
|
# cartesian_product [[1;2];[];[4;5;6]] = [];;
|
||||||
|
# cartesian_product [[1;2];[3];[4];[5];[6]] |> sort =
|
||||||
|
[[1;3;4;5;6];[2;3;4;5;6]];;
|
||||||
|
]}
|
||||||
|
invariant: [cartesian_product l = map_product id l].
|
||||||
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val map_product_l : f:('a -> 'b list) -> 'a list -> 'b list list
|
val map_product_l : f:('a -> 'b list) -> 'a list -> 'b list list
|
||||||
(** @since 2.2 *)
|
(** [map_product_l f l] maps each element of [l] to a list of
|
||||||
|
objects of type ['b] using [f].
|
||||||
|
We obtain [[l1;l2;...;ln]] where [length l=n] and [li : 'b list].
|
||||||
|
Then, it returns all the ways of picking exactly one element per [li].
|
||||||
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -149,7 +193,7 @@ val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) ->
|
||||||
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
|
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
|
||||||
@since 2.3 *)
|
@since 2.3 *)
|
||||||
|
|
||||||
val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t
|
val join : join_row:(('a -> 'b -> 'c option) [@keep_label]) -> 'a t -> 'b t -> 'c t
|
||||||
(** [join ~join_row a b] combines every element of [a] with every
|
(** [join ~join_row a b] combines every element of [a] with every
|
||||||
element of [b] using [join_row]. If [join_row] returns None, then
|
element of [b] using [join_row]. If [join_row] returns None, then
|
||||||
the two elements do not combine. Assume that [b] allows for multiple
|
the two elements do not combine. Assume that [b] allows for multiple
|
||||||
|
|
@ -158,7 +202,7 @@ val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t
|
||||||
|
|
||||||
val join_by : ?eq:('key -> 'key -> bool) -> ?hash:('key -> int) ->
|
val join_by : ?eq:('key -> 'key -> bool) -> ?hash:('key -> int) ->
|
||||||
('a -> 'key) -> ('b -> 'key) ->
|
('a -> 'key) -> ('b -> 'key) ->
|
||||||
merge:('key -> 'a -> 'b -> 'c option) ->
|
merge:(('key -> 'a -> 'b -> 'c option) [@keep_label]) ->
|
||||||
'a t ->
|
'a t ->
|
||||||
'b t ->
|
'b t ->
|
||||||
'c t
|
'c t
|
||||||
|
|
@ -173,7 +217,7 @@ val join_by : ?eq:('key -> 'key -> bool) -> ?hash:('key -> int) ->
|
||||||
|
|
||||||
val join_all_by : ?eq:('key -> 'key -> bool) -> ?hash:('key -> int) ->
|
val join_all_by : ?eq:('key -> 'key -> bool) -> ?hash:('key -> int) ->
|
||||||
('a -> 'key) -> ('b -> 'key) ->
|
('a -> 'key) -> ('b -> 'key) ->
|
||||||
merge:('key -> 'a list -> 'b list -> 'c option) ->
|
merge:(('key -> 'a list -> 'b list -> 'c option) [@keep_label]) ->
|
||||||
'a t ->
|
'a t ->
|
||||||
'b t ->
|
'b t ->
|
||||||
'c t
|
'c t
|
||||||
|
|
@ -201,7 +245,6 @@ val group_join_by : ?eq:('a -> 'a -> bool) -> ?hash:('a -> int) ->
|
||||||
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
|
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
|
||||||
@since 2.3 *)
|
@since 2.3 *)
|
||||||
|
|
||||||
|
|
||||||
val sublists_of_len :
|
val sublists_of_len :
|
||||||
?last:('a list -> 'a list option) ->
|
?last:('a list -> 'a list option) ->
|
||||||
?offset:int ->
|
?offset:int ->
|
||||||
|
|
@ -212,24 +255,43 @@ val sublists_of_len :
|
||||||
By default, these sub-lists are non overlapping:
|
By default, these sub-lists are non overlapping:
|
||||||
[sublists_of_len 2 [1;2;3;4;5;6]] returns [[1;2]; [3;4]; [5;6]].
|
[sublists_of_len 2 [1;2;3;4;5;6]] returns [[1;2]; [3;4]; [5;6]].
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- [sublists_of_len 2 [1;2;3;4;5;6] = [[1;2]; [3;4]; [5;6]]].
|
||||||
|
- [sublists_of_len 2 ~offset:3 [1;2;3;4;5;6] = [1;2];[4;5]].
|
||||||
|
- [sublists_of_len 3 ~last:CCOpt.return [1;2;3;4] = [1;2;3];[4]].
|
||||||
|
- [sublists_of_len 2 [1;2;3;4;5] = [[1;2]; [3;4]]].
|
||||||
|
|
||||||
|
@param offset the number of elements skipped between two consecutive
|
||||||
|
sub-lists. By default it is [n]. If [offset < n], the sub-lists
|
||||||
|
will overlap; if [offset > n], some elements will not appear at all.
|
||||||
|
@param last if provided and the last group of elements [g] is such
|
||||||
|
that [length g < n], [last g] is called. If [last g = Some g'],
|
||||||
|
[g'] is appended; otherwise [g] is dropped.
|
||||||
|
If [last = CCOpt.return], it will simply keep the last group.
|
||||||
|
By default, [last = fun _ -> None], i.e. the last group is dropped if shorter than [n].
|
||||||
|
@raise Invalid_argument if [offset <= 0] or [n <= 0].
|
||||||
See {!CCList.sublists_of_len} for more details.
|
See {!CCList.sublists_of_len} for more details.
|
||||||
|
|
||||||
@since 1.5 *)
|
@since 1.0, but only
|
||||||
|
@since 1.5 with labels *)
|
||||||
|
|
||||||
val intersperse : x:'a -> 'a list -> 'a list
|
val intersperse : x:'a -> 'a list -> 'a list
|
||||||
(** Insert the first argument between every element of the list.
|
(** Insert the first argument between every element of the list.
|
||||||
@since 2.2 *)
|
@since 2.1, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val interleave : 'a list -> 'a list -> 'a list
|
val interleave : 'a list -> 'a list -> 'a list
|
||||||
(** [interleave [x1…xn] [y1…ym]] is [x1,y1,x2,y2,…] and finishes with
|
(** [interleave [x1…xn] [y1…ym]] is [x1,y1,x2,y2,…] and finishes with
|
||||||
the suffix of the longest list.
|
the suffix of the longest list.
|
||||||
@since 2.2 *)
|
@since 2.1, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val pure : 'a -> 'a t
|
val pure : 'a -> 'a t
|
||||||
(** [pure] is [return]. *)
|
(** [pure] is [return]. *)
|
||||||
|
|
||||||
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
||||||
(** [funs <*> l] is [product fun f x -> f x) funs l]. *)
|
(** [funs <*> l] is [product (fun f x -> f x) funs l]. *)
|
||||||
|
|
||||||
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
|
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
|
||||||
(** [(<$>)] is [map]. *)
|
(** [(<$>)] is [map]. *)
|
||||||
|
|
@ -264,7 +326,9 @@ val drop_while : f:('a -> bool) -> 'a t -> 'a t
|
||||||
@since 0.13 *)
|
@since 0.13 *)
|
||||||
|
|
||||||
val take_drop_while : f:('a -> bool) -> 'a t -> 'a t * 'a t
|
val take_drop_while : f:('a -> bool) -> 'a t -> 'a t * 'a t
|
||||||
(** @since 2.2 *)
|
(** [take_drop_while p l] = [take_while p l, drop_while p l].
|
||||||
|
@since 1.2, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val last : int -> 'a t -> 'a t
|
val last : int -> 'a t -> 'a t
|
||||||
(** [last n l] takes the last [n] elements of [l] (or less if
|
(** [last n l] takes the last [n] elements of [l] (or less if
|
||||||
|
|
@ -288,7 +352,9 @@ val find_pred : f:('a -> bool) -> 'a t -> 'a option
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
val find_opt : f:('a -> bool) -> 'a t -> 'a option
|
val find_opt : f:('a -> bool) -> 'a t -> 'a option
|
||||||
(** @since 2.2 *)
|
(** Safe version of {!find}.
|
||||||
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val find_pred_exn : f:('a -> bool) -> 'a t -> 'a
|
val find_pred_exn : f:('a -> bool) -> 'a t -> 'a
|
||||||
(** Unsafe version of {!find_pred}.
|
(** Unsafe version of {!find_pred}.
|
||||||
|
|
@ -309,7 +375,8 @@ 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],
|
(** [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) [@keep_label]) -> key:'a -> 'a t -> 'a t
|
||||||
|
(* FIXME: the original CCList.mli uses ~x instead of ~key !! *)
|
||||||
(** [remove ~key l] removes every instance of [key] from [l]. Tail-recursive.
|
(** [remove ~key l] removes every instance of [key] from [l]. Tail-recursive.
|
||||||
@param eq equality function.
|
@param eq equality function.
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
@ -320,48 +387,59 @@ val filter_map : f:('a -> 'b option) -> 'a t -> 'b t
|
||||||
Map and remove elements at the same time. *)
|
Map and remove elements at the same time. *)
|
||||||
|
|
||||||
val keep_some : 'a option t -> 'a t
|
val keep_some : 'a option t -> 'a t
|
||||||
(** @since 2.2 *)
|
(** [keep_some l] retains only elements of the form [Some x].
|
||||||
|
Like [filter_map CCFun.id].
|
||||||
|
@since 1.3, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val keep_ok : ('a, _) Result.result t -> 'a t
|
val keep_ok : ('a, _) Result.result t -> 'a t
|
||||||
(** @since 2.2 *)
|
(** [keep_ok l] retains only elements of the form [Ok x].
|
||||||
|
@since 1.3, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val all_some : 'a option t -> 'a t option
|
val all_some : 'a option t -> 'a t option
|
||||||
(** @since 2.2 *)
|
(** [all_some l] returns [Some l'] if all elements of [l] are of the form [Some x],
|
||||||
|
or [None] otherwise.
|
||||||
|
@since 1.3, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val all_ok : ('a, 'err) Result.result t -> ('a t, 'err) Result.result
|
val all_ok : ('a, 'err) Result.result t -> ('a t, 'err) Result.result
|
||||||
(** @since 2.2 *)
|
(** [all_ok l] returns [Ok l'] if all elements of [l] are of the form [Ok x],
|
||||||
|
or [Error e] otherwise (with the first error met).
|
||||||
|
@since 1.3, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val sorted_merge : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
val sorted_merge : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> 'a list -> 'a list
|
||||||
(** Merges elements from both sorted list. *)
|
(** Merge elements from both sorted list. *)
|
||||||
|
|
||||||
val sort_uniq : cmp:('a -> 'a -> int) -> 'a list -> 'a list
|
val sort_uniq : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> 'a list
|
||||||
(** Sort the list and remove duplicate elements. *)
|
(** Sort the list and remove duplicate elements. *)
|
||||||
|
|
||||||
val sorted_merge_uniq : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
val sorted_merge_uniq : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> 'a list -> 'a list
|
||||||
(** [sorted_merge_uniq l1 l2] merges the sorted lists [l1] and [l2] and
|
(** [sorted_merge_uniq l1 l2] merges the sorted lists [l1] and [l2] and
|
||||||
removes duplicates.
|
removes duplicates.
|
||||||
@since 0.10 *)
|
@since 0.10 *)
|
||||||
|
|
||||||
val is_sorted : cmp:('a -> 'a -> int) -> 'a list -> bool
|
val is_sorted : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> bool
|
||||||
(** [is_sorted l] returns [true] iff [l] is sorted (according to given order).
|
(** [is_sorted l] returns [true] iff [l] is sorted (according to given order).
|
||||||
@param cmp the comparison function (default [Pervasives.compare]).
|
@param cmp the comparison function (default [Pervasives.compare]).
|
||||||
@since 0.17 *)
|
@since 0.17 *)
|
||||||
|
|
||||||
val sorted_insert : cmp:('a -> 'a -> int) -> ?uniq:bool -> 'a -> 'a list -> 'a list
|
val sorted_insert : cmp:(('a -> 'a -> int) [@keep_label]) -> ?uniq:bool -> 'a -> 'a list -> 'a list
|
||||||
(** [sorted_insert x l] inserts [x] into [l] such that, if [l] was sorted,
|
(** [sorted_insert x l] inserts [x] into [l] such that, if [l] was sorted,
|
||||||
then [sorted_insert x l] is sorted too.
|
then [sorted_insert x l] is sorted too.
|
||||||
@param uniq if true and [x] is already in sorted position in [l], then
|
@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).
|
[x] is not duplicated. Default [false] ([x] will be inserted in any case).
|
||||||
@since 0.17 *)
|
@since 0.17 *)
|
||||||
|
|
||||||
val uniq_succ : eq:('a -> 'a -> bool) -> 'a list -> 'a list
|
val uniq_succ : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a list -> 'a list
|
||||||
(** [uniq_succ l] removes duplicate elements that occur one next to the other.
|
(** [uniq_succ l] removes duplicate elements that occur one next to the other.
|
||||||
Examples:
|
Examples:
|
||||||
[uniq_succ [1;2;1] = [1;2;1]].
|
[uniq_succ [1;2;1] = [1;2;1]].
|
||||||
[uniq_succ [1;1;2] = [1;2]].
|
[uniq_succ [1;1;2] = [1;2]].
|
||||||
@since 0.10 *)
|
@since 0.10 *)
|
||||||
|
|
||||||
val group_succ : eq:('a -> 'a -> bool) -> 'a list -> 'a list list
|
val group_succ : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a list -> 'a list list
|
||||||
(** [group_succ ~eq l] groups together consecutive elements that are equal
|
(** [group_succ ~eq l] groups together consecutive elements that are equal
|
||||||
according to [eq].
|
according to [eq].
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
@ -379,13 +457,19 @@ val iteri : f:(int -> 'a -> unit) -> 'a t -> unit
|
||||||
itself as second argument. *)
|
itself as second argument. *)
|
||||||
|
|
||||||
val iteri2 : f:(int -> 'a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
val iteri2 : f:(int -> 'a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
||||||
(** @since 2.2 *)
|
(** Iter on two lists.
|
||||||
|
@raise Invalid_argument when lists do not have the same length.
|
||||||
|
@since 2.0, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val foldi : f:('b -> int -> 'a -> 'b) -> init:'b -> 'a t -> 'b
|
val foldi : f:('b -> int -> 'a -> 'b) -> init:'b -> 'a t -> 'b
|
||||||
(** Like [fold] but it also passes in the index of each element to the folded function. Tail-recursive. *)
|
(** Like [fold] but it also passes in the index of each element to the folded function. Tail-recursive. *)
|
||||||
|
|
||||||
val foldi2 : f:('c -> int -> 'a -> 'b -> 'c) -> init:'c -> 'a t -> 'b t -> 'c
|
val foldi2 : f:('c -> int -> 'a -> 'b -> 'c) -> init:'c -> 'a t -> 'b t -> 'c
|
||||||
(** @since 2.2 *)
|
(** Fold on two lists, with index.
|
||||||
|
@raise Invalid_argument when lists do not have the same length.
|
||||||
|
@since 2.0, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val get_at_idx : int -> 'a t -> 'a option
|
val get_at_idx : int -> 'a t -> 'a option
|
||||||
(** Get by index in the list.
|
(** Get by index in the list.
|
||||||
|
|
@ -393,7 +477,10 @@ val get_at_idx : int -> 'a t -> 'a option
|
||||||
of the list. *)
|
of the list. *)
|
||||||
|
|
||||||
val nth_opt : 'a t -> int -> 'a option
|
val nth_opt : 'a t -> int -> 'a option
|
||||||
(** @since 2.2 *)
|
(** Safe version of {!nth}.
|
||||||
|
@raise Invalid_argument if the int is negative.
|
||||||
|
@since 1.5, but only
|
||||||
|
@since 2.2 with labels *)
|
||||||
|
|
||||||
val get_at_idx_exn : int -> 'a t -> 'a
|
val get_at_idx_exn : int -> 'a t -> 'a
|
||||||
(** Get the i-th element, or
|
(** Get the i-th element, or
|
||||||
|
|
@ -424,38 +511,38 @@ val remove_at_idx : int -> 'a t -> 'a t
|
||||||
Those operations maintain the invariant that the list does not
|
Those operations maintain the invariant that the list does not
|
||||||
contain duplicates (if it already satisfies it). *)
|
contain duplicates (if it already satisfies it). *)
|
||||||
|
|
||||||
val add_nodup : eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t
|
val add_nodup : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a -> 'a t -> 'a t
|
||||||
(** [add_nodup x set] adds [x] to [set] if it was not already present. Linear time.
|
(** [add_nodup x set] adds [x] to [set] if it was not already present. Linear time.
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
val remove_one : eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t
|
val remove_one : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a -> 'a t -> 'a t
|
||||||
(** [remove_one x set] removes one occurrence of [x] from [set]. Linear time.
|
(** [remove_one x set] removes one occurrence of [x] from [set]. Linear time.
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
val mem : eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool
|
val mem : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a -> 'a t -> bool
|
||||||
(** Membership to the list. Linear time. *)
|
(** Membership to the list. Linear time. *)
|
||||||
|
|
||||||
val subset : eq:('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
val subset : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a t -> 'a t -> bool
|
||||||
(** Test for inclusion. *)
|
(** Test for inclusion. *)
|
||||||
|
|
||||||
val uniq : eq:('a -> 'a -> bool) -> 'a t -> 'a t
|
val uniq : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a t -> 'a t
|
||||||
(** Remove duplicates w.r.t the equality predicate.
|
(** Remove duplicates w.r.t the equality predicate.
|
||||||
Complexity is quadratic in the length of the list, but the order
|
Complexity is quadratic in the length of the list, but the order
|
||||||
of elements is preserved. If you wish for a faster de-duplication
|
of elements is preserved. If you wish for a faster de-duplication
|
||||||
but do not care about the order, use {!sort_uniq}. *)
|
but do not care about the order, use {!sort_uniq}. *)
|
||||||
|
|
||||||
val union : eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t
|
val union : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a t -> 'a t -> 'a t
|
||||||
(** List union. Complexity is product of length of inputs. *)
|
(** List union. Complexity is product of length of inputs. *)
|
||||||
|
|
||||||
val inter : eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t
|
val inter : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a t -> 'a t -> 'a t
|
||||||
(** List intersection. Complexity is product of length of inputs. *)
|
(** List intersection. Complexity is product of length of inputs. *)
|
||||||
|
|
||||||
(** {2 Other Constructors} *)
|
(** {2 Other Constructors} *)
|
||||||
|
|
||||||
val range_by : step:int -> int -> int -> int t
|
val range_by : step:(int [@keep_label]) -> int -> int -> int t
|
||||||
(** [range_by ~step i j] iterates on integers from [i] to [j] included,
|
(** [range_by ~step i j] iterates on integers from [i] to [j] included,
|
||||||
where the difference between successive elements is [step].
|
where the difference between successive elements is [step].
|
||||||
use a negative [step] for a decreasing list.
|
Use a negative [step] for a decreasing list.
|
||||||
@raise Invalid_argument if [step=0].
|
@raise Invalid_argument if [step=0].
|
||||||
@since 0.18 *)
|
@since 0.18 *)
|
||||||
|
|
||||||
|
|
@ -485,49 +572,52 @@ val repeat : int -> 'a t -> 'a t
|
||||||
module Assoc : sig
|
module Assoc : sig
|
||||||
type ('a, 'b) t = ('a*'b) list
|
type ('a, 'b) t = ('a*'b) list
|
||||||
|
|
||||||
val get : eq:('a->'a->bool) -> 'a -> ('a,'b) t -> 'b option
|
val get : eq:(('a->'a->bool) [@keep_label]) -> 'a -> ('a,'b) t -> 'b option
|
||||||
(** Find the element. *)
|
(** Find the element. *)
|
||||||
|
|
||||||
val get_exn : eq:('a->'a->bool) -> 'a -> ('a,'b) t -> 'b
|
val get_exn : eq:(('a->'a->bool) [@keep_label]) -> 'a -> ('a,'b) t -> 'b
|
||||||
(** Like [get], but unsafe.
|
(** Like [get], but unsafe.
|
||||||
@raise Not_found if the element is not present. *)
|
@raise Not_found if the element is not present. *)
|
||||||
|
|
||||||
val set : eq:('a->'a->bool) -> 'a -> 'b -> ('a,'b) t -> ('a,'b) t
|
val set : eq:(('a->'a->bool) [@keep_label]) -> 'a -> 'b -> ('a,'b) t -> ('a,'b) t
|
||||||
(** Add the binding into the list (erase it if already present). *)
|
(** Add the binding into the list (erase it if already present). *)
|
||||||
|
|
||||||
val mem : eq:('a->'a->bool) -> 'a -> ('a,_) t -> bool
|
val mem : eq:(('a->'a->bool) [@keep_label]) -> 'a -> ('a,_) t -> bool
|
||||||
(** [mem x l] returns [true] iff [x] is a key in [l].
|
(** [mem x l] returns [true] iff [x] is a key in [l].
|
||||||
@since 0.16 *)
|
@since 0.16 *)
|
||||||
|
|
||||||
val update :
|
val update :
|
||||||
eq:('a->'a->bool) -> f:('b option -> 'b option) -> 'a -> ('a,'b) t -> ('a,'b) t
|
eq:(('a->'a->bool) [@keep_label]) -> f:('b option -> 'b option) -> 'a -> ('a,'b) t -> ('a,'b) t
|
||||||
|
(* FIXME: the original no labels mli kept the ~f label ! *)
|
||||||
(** [update k ~f l] updates [l] on the key [k], by calling [f (get l k)]
|
(** [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
|
and removing [k] if it returns [None], mapping [k] to [v'] if it
|
||||||
returns [Some v'].
|
returns [Some v'].
|
||||||
@since 0.16 *)
|
@since 0.16 *)
|
||||||
|
|
||||||
val remove : eq:('a->'a->bool) -> 'a -> ('a,'b) t -> ('a,'b) t
|
val remove : eq:(('a->'a->bool) [@keep_label]) -> 'a -> ('a,'b) t -> ('a,'b) t
|
||||||
(** [remove x l] removes the first occurrence of [k] from [l].
|
(** [remove x l] removes the first occurrence of [k] from [l].
|
||||||
@since 0.17 *)
|
@since 0.17 *)
|
||||||
end
|
end
|
||||||
|
|
||||||
val assoc : eq:('a -> 'a -> bool) -> 'a -> ('a * 'b) t -> 'b
|
val assoc : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a -> ('a * 'b) t -> 'b
|
||||||
(** Like [Assoc.get_exn].
|
(** Like [Assoc.get_exn].
|
||||||
@since 2.0 *)
|
@since 2.0 *)
|
||||||
|
|
||||||
val assoc_opt : eq:('a -> 'a -> bool) -> 'a -> ('a * 'b) t -> 'b option
|
val assoc_opt : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a -> ('a * 'b) t -> 'b option
|
||||||
(** Like [Assoc.get].
|
(** Like [Assoc.get].
|
||||||
@since 2.0 *)
|
@since 1.5, but only
|
||||||
|
@since 2.0 with labels *)
|
||||||
|
|
||||||
val assq_opt : 'a -> ('a * 'b) t -> 'b option
|
val assq_opt : 'a -> ('a * 'b) t -> 'b option
|
||||||
(** Safe version of {!assq}.
|
(** Safe version of {!assq}.
|
||||||
@since 2.0 *)
|
@since 1.5, but only
|
||||||
|
@since 2.0 with labels *)
|
||||||
|
|
||||||
val mem_assoc : eq:('a -> 'a -> bool) -> 'a -> ('a * _) t -> bool
|
val mem_assoc : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a -> ('a * _) t -> bool
|
||||||
(** Like [Assoc.mem].
|
(** Like [Assoc.mem].
|
||||||
@since 2.0 *)
|
@since 2.0 *)
|
||||||
|
|
||||||
val remove_assoc : eq:('a -> 'a -> bool) -> 'a -> ('a * 'b) t -> ('a * 'b) t
|
val remove_assoc : eq:(('a -> 'a -> bool) [@keep_label]) -> 'a -> ('a * 'b) t -> ('a * 'b) t
|
||||||
(** Like [Assoc.remove].
|
(** Like [Assoc.remove].
|
||||||
@since 2.0 *)
|
@since 2.0 *)
|
||||||
|
|
||||||
|
|
@ -567,7 +657,6 @@ module type MONAD = sig
|
||||||
|
|
||||||
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
(** Monadic [bind]. *)
|
(** Monadic [bind]. *)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Traverse(M : MONAD) : sig
|
module Traverse(M : MONAD) : sig
|
||||||
|
|
@ -599,19 +688,22 @@ val to_seq : 'a t -> 'a sequence
|
||||||
(** Return a [sequence] of the elements of the list. *)
|
(** Return a [sequence] of the elements of the list. *)
|
||||||
|
|
||||||
val of_seq : 'a sequence -> 'a t
|
val of_seq : 'a sequence -> 'a t
|
||||||
(** Build a list from a given [sequence]. *)
|
(** Build a list from a given [sequence].
|
||||||
|
In the result, elements appear in the same order as they did in the source [sequence]. *)
|
||||||
|
|
||||||
val to_gen : 'a t -> 'a gen
|
val to_gen : 'a t -> 'a gen
|
||||||
(** Return a [gen] of the elements of the list. *)
|
(** Return a [gen] of the elements of the list. *)
|
||||||
|
|
||||||
val of_gen : 'a gen -> 'a t
|
val of_gen : 'a gen -> 'a t
|
||||||
(** Build a list from a given [gen]. *)
|
(** Build a list from a given [gen].
|
||||||
|
In the result, elements appear in the same order as they did in the source [gen]. *)
|
||||||
|
|
||||||
val to_klist : 'a t -> 'a klist
|
val to_klist : 'a t -> 'a klist
|
||||||
(** Return a [klist] of the elements of the list. *)
|
(** Return a [klist] of the elements of the list. *)
|
||||||
|
|
||||||
val of_klist : 'a klist -> 'a t
|
val of_klist : 'a klist -> 'a t
|
||||||
(** Build a list from a given [klist]. *)
|
(** Build a list from a given [klist].
|
||||||
|
In the result, elements appear in the same order as they did in the source [klist]. *)
|
||||||
|
|
||||||
(** {2 Infix Operators}
|
(** {2 Infix Operators}
|
||||||
It is convenient to {!open CCList.Infix} to access the infix operators
|
It is convenient to {!open CCList.Infix} to access the infix operators
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,14 @@
|
||||||
|
(rule
|
||||||
|
(targets CCArray.mli)
|
||||||
|
(deps CCArrayLabels.mli)
|
||||||
|
(mode promote)
|
||||||
|
(action (run ../unlabel.exe %{deps} %{targets})))
|
||||||
|
|
||||||
|
(rule
|
||||||
|
(targets CCList.mli)
|
||||||
|
(deps CCListLabels.mli)
|
||||||
|
(mode promote)
|
||||||
|
(action (run ../unlabel.exe %{deps} %{targets})))
|
||||||
|
|
||||||
(library
|
(library
|
||||||
(name containers)
|
(name containers)
|
||||||
|
|
|
||||||
8
src/dune
8
src/dune
|
|
@ -1,12 +1,16 @@
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(name mkflags)
|
(name mkflags)
|
||||||
|
(modules mkflags)
|
||||||
(libraries dune.configurator))
|
(libraries dune.configurator))
|
||||||
|
|
||||||
|
(executable
|
||||||
|
(name unlabel)
|
||||||
|
(modules unlabel)
|
||||||
|
(libraries str compiler-libs.common))
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
(targets flambda.flags)
|
(targets flambda.flags)
|
||||||
(mode fallback)
|
(mode fallback)
|
||||||
(action
|
(action
|
||||||
(run ./mkflags.exe))
|
(run ./mkflags.exe))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
246
src/unlabel.ml
Normal file
246
src/unlabel.ml
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
(* search for first occurence of pat in s *)
|
||||||
|
let rec search pat s pos =
|
||||||
|
let rec compare i =
|
||||||
|
if i >= String.length pat
|
||||||
|
then true
|
||||||
|
else if pat.[i] = s.[pos+i]
|
||||||
|
then compare (i+1)
|
||||||
|
else false
|
||||||
|
in
|
||||||
|
if pos > String.length s - String.length pat
|
||||||
|
then raise Not_found
|
||||||
|
else if compare 0
|
||||||
|
then pos
|
||||||
|
else search pat s (pos+1)
|
||||||
|
;;
|
||||||
|
|
||||||
|
(* search all non-overlapping occurences of pat in s *)
|
||||||
|
let search_all pat s =
|
||||||
|
let rec search_rest acc pos =
|
||||||
|
let next =
|
||||||
|
try Some (search pat s pos) with
|
||||||
|
Not_found -> None
|
||||||
|
in
|
||||||
|
match next with
|
||||||
|
| None -> acc
|
||||||
|
| Some pos -> search_rest (pos::acc) (pos + String.length pat)
|
||||||
|
in
|
||||||
|
List.rev (search_rest [] 0)
|
||||||
|
;;
|
||||||
|
|
||||||
|
(* replase first occurence of pat with subst in s *)
|
||||||
|
let replace_first pat subst s =
|
||||||
|
let pos = search pat s 0 in
|
||||||
|
let patl = String.length pat
|
||||||
|
and substl = String.length subst in
|
||||||
|
let buf = Bytes.create (String.length s - patl + substl) in
|
||||||
|
Bytes.blit_string s 0 buf 0 pos;
|
||||||
|
Bytes.blit_string subst 0 buf pos substl;
|
||||||
|
Bytes.blit_string
|
||||||
|
s (pos + patl)
|
||||||
|
buf (pos + substl)
|
||||||
|
(String.length s - pos - patl);
|
||||||
|
Bytes.unsafe_to_string buf
|
||||||
|
;;
|
||||||
|
|
||||||
|
(* replase first occurence of pat with subst in s *)
|
||||||
|
let replace_all pat subst s =
|
||||||
|
let pos = search_all pat s in
|
||||||
|
let patl = String.length pat
|
||||||
|
and substl = String.length subst in
|
||||||
|
let len = String.length s + List.length pos * (substl - patl) in
|
||||||
|
let buf = Bytes.create len in
|
||||||
|
let rec loop src_pos dst_pos = function
|
||||||
|
| [] ->
|
||||||
|
Bytes.blit_string s src_pos buf dst_pos (String.length s - src_pos)
|
||||||
|
| pat_pos :: tail ->
|
||||||
|
let headl = pat_pos - src_pos in
|
||||||
|
Bytes.blit_string s src_pos buf dst_pos headl;
|
||||||
|
Bytes.blit_string subst 0 buf (dst_pos + headl) substl;
|
||||||
|
loop
|
||||||
|
(src_pos + headl + patl)
|
||||||
|
(dst_pos + headl + substl)
|
||||||
|
tail
|
||||||
|
in loop 0 0 pos;
|
||||||
|
Bytes.unsafe_to_string buf
|
||||||
|
;;
|
||||||
|
|
||||||
|
let match_closeparen s i =
|
||||||
|
assert (s.[i] = ')');
|
||||||
|
let rec loop i count =
|
||||||
|
match s.[i] with
|
||||||
|
| '(' when count = 0 -> i
|
||||||
|
| '(' -> loop (i-1) (count-1)
|
||||||
|
| ')' -> loop (i-1) (count+1)
|
||||||
|
| _ -> loop (i-1) count
|
||||||
|
in loop (i-1) 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
let slurp_file file =
|
||||||
|
let ch = open_in file in
|
||||||
|
let buf = Buffer.create (min 1024 (in_channel_length ch)) in
|
||||||
|
try
|
||||||
|
while true do Buffer.add_channel buf ch 4096 done;
|
||||||
|
assert false
|
||||||
|
with
|
||||||
|
| End_of_file ->
|
||||||
|
close_in ch;
|
||||||
|
Bytes.unsafe_to_string (Buffer.to_bytes buf)
|
||||||
|
;;
|
||||||
|
|
||||||
|
let () =
|
||||||
|
assert (Array.length Sys.argv = 3);
|
||||||
|
let labelled_filename = Sys.argv.(1) in (* CCArrayLabels.mli *)
|
||||||
|
let unlabelled_filename = Sys.argv.(2) in (* CCArray.ml *)
|
||||||
|
let labelled_name = (* ArrayLabels *)
|
||||||
|
let basename =
|
||||||
|
Compenv.module_of_filename Format.err_formatter
|
||||||
|
labelled_filename
|
||||||
|
labelled_filename
|
||||||
|
in
|
||||||
|
assert (basename.[0] = 'C' && basename.[1] = 'C');
|
||||||
|
String.sub basename 2 (String.length basename - 2)
|
||||||
|
in
|
||||||
|
let unlabelled_name = (* Array *)
|
||||||
|
replace_first "Labels" "" labelled_name
|
||||||
|
in
|
||||||
|
let labelled_text = slurp_file labelled_filename in
|
||||||
|
let lexbuf = Lexing.from_string labelled_text in
|
||||||
|
Location.init lexbuf labelled_filename;
|
||||||
|
let labelled_ast = Parse.interface lexbuf in
|
||||||
|
(* stack of replacements to perform on the labelled_text.
|
||||||
|
* perform them in one run later so that the character counts
|
||||||
|
* won't be affected by earlier replacements. *)
|
||||||
|
let replacements = ref [] in
|
||||||
|
(* function removing '~' from docstring attributes where appropriate. *)
|
||||||
|
let strip_attributes labels attributes =
|
||||||
|
List.iter
|
||||||
|
begin function
|
||||||
|
| ({ Asttypes.txt = "ocaml.doc"; _ },
|
||||||
|
Parsetree.PStr [{pstr_loc =
|
||||||
|
{ loc_start = {pos_cnum = start; _}
|
||||||
|
; loc_end = {pos_cnum = stop; _}
|
||||||
|
; _}
|
||||||
|
; _
|
||||||
|
}]) ->
|
||||||
|
let docstring =
|
||||||
|
List.fold_left
|
||||||
|
(fun docstring label ->
|
||||||
|
replace_all ("~" ^ label) label docstring)
|
||||||
|
(String.sub labelled_text start (stop-start))
|
||||||
|
labels
|
||||||
|
in
|
||||||
|
replacements := (start, stop-start, docstring) :: !replacements
|
||||||
|
| _ -> ()
|
||||||
|
end
|
||||||
|
attributes
|
||||||
|
in
|
||||||
|
let iterator =
|
||||||
|
let open Ast_iterator in
|
||||||
|
let open Parsetree in
|
||||||
|
{ Ast_iterator.default_iterator with
|
||||||
|
value_description = begin fun iterator
|
||||||
|
{ pval_name = { txt = _name; _ }
|
||||||
|
; pval_type
|
||||||
|
; pval_prim = _
|
||||||
|
; pval_attributes
|
||||||
|
; pval_loc
|
||||||
|
} ->
|
||||||
|
let rec loop = function
|
||||||
|
(* match function type with label *)
|
||||||
|
| { ptyp_desc = Ptyp_arrow (Labelled label, left, right)
|
||||||
|
; ptyp_loc = {loc_start = {Lexing.pos_cnum = start; _}; _}
|
||||||
|
; ptyp_attributes
|
||||||
|
; _}
|
||||||
|
when
|
||||||
|
(* check that the argument type is not marked with [@keep_label] *)
|
||||||
|
List.for_all
|
||||||
|
(fun ({Asttypes.txt; _}, _) -> txt <> "keep_label")
|
||||||
|
left.ptyp_attributes
|
||||||
|
->
|
||||||
|
assert (label = String.sub labelled_text start (String.length label));
|
||||||
|
let colon = String.index_from labelled_text start ':' in
|
||||||
|
(* remove label *)
|
||||||
|
replacements := (start, colon+1-start, "") :: !replacements;
|
||||||
|
(* remove labels from associated docstrings *)
|
||||||
|
strip_attributes [label] ptyp_attributes;
|
||||||
|
label :: loop right
|
||||||
|
| { ptyp_desc = Ptyp_arrow (_, _left, right); _} ->
|
||||||
|
loop right
|
||||||
|
| _ -> []
|
||||||
|
in
|
||||||
|
let labels = loop pval_type in
|
||||||
|
strip_attributes labels pval_attributes;
|
||||||
|
iterator.attributes iterator pval_attributes;
|
||||||
|
iterator.location iterator pval_loc;
|
||||||
|
iterator.typ iterator pval_type;
|
||||||
|
end
|
||||||
|
; attribute = begin fun iterator
|
||||||
|
({Asttypes.txt
|
||||||
|
; loc =
|
||||||
|
{ loc_start = {pos_cnum = start; _}
|
||||||
|
; loc_end = {pos_cnum = stop; _}
|
||||||
|
; _} as loc
|
||||||
|
}, _) ->
|
||||||
|
if txt = "keep_label"
|
||||||
|
then begin
|
||||||
|
(* start and stop positions mark the location of only the label name.
|
||||||
|
* Therefore search for enclosing brackets. *)
|
||||||
|
let start = String.rindex_from labelled_text start '['
|
||||||
|
and stop = String. index_from labelled_text stop ']' in
|
||||||
|
(* remove leading ' ', too *)
|
||||||
|
let start =
|
||||||
|
if labelled_text.[start-1] = ' ' then start-1 else start
|
||||||
|
in
|
||||||
|
(* if a closing paren follows, remove this and the matching paren,
|
||||||
|
* this will hopefully be the right thing to do. *)
|
||||||
|
let stop =
|
||||||
|
if labelled_text.[stop+1] = ')'
|
||||||
|
then
|
||||||
|
let openp = match_closeparen labelled_text (stop+1) in
|
||||||
|
replacements := (openp, 1, "") :: !replacements;
|
||||||
|
stop+1
|
||||||
|
else
|
||||||
|
stop
|
||||||
|
in
|
||||||
|
replacements := (start, stop-start+1, "") :: !replacements;
|
||||||
|
end;
|
||||||
|
iterator.location iterator loc
|
||||||
|
end
|
||||||
|
}
|
||||||
|
in
|
||||||
|
iterator.signature iterator labelled_ast;
|
||||||
|
|
||||||
|
(* sort replacements in ascending order. *)
|
||||||
|
let replacements =
|
||||||
|
List.sort (fun (p1,_,_) (p2,_,_) -> compare p1 p2) !replacements
|
||||||
|
in
|
||||||
|
|
||||||
|
(* perform the replacements by blitting to a buffer. *)
|
||||||
|
let unlabelled_text = Buffer.create (String.length labelled_text) in
|
||||||
|
List.fold_left begin fun start (pos,len,subst) ->
|
||||||
|
assert (pos >= start);
|
||||||
|
Buffer.add_substring unlabelled_text labelled_text start (pos - start);
|
||||||
|
Buffer.add_string unlabelled_text subst;
|
||||||
|
pos+len
|
||||||
|
end
|
||||||
|
0
|
||||||
|
replacements
|
||||||
|
|> fun start ->
|
||||||
|
Buffer.add_substring unlabelled_text
|
||||||
|
labelled_text start (String.length labelled_text - start);
|
||||||
|
|
||||||
|
let unlabelled_text =
|
||||||
|
Buffer.contents unlabelled_text
|
||||||
|
(* CCArrayLabels -> CCArray *)
|
||||||
|
|> replace_all labelled_name unlabelled_name
|
||||||
|
in
|
||||||
|
|
||||||
|
let out = open_out unlabelled_filename in
|
||||||
|
output_string out (
|
||||||
|
"(* AUTOGENERATED FROM " ^
|
||||||
|
labelled_filename
|
||||||
|
^ " *)\n\n");
|
||||||
|
output_string out unlabelled_text;
|
||||||
|
close_out out;
|
||||||
|
;;
|
||||||
Loading…
Add table
Reference in a new issue