mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2026-01-28 11:54:51 -05:00
use subtree gen/ for CCGen (symlink)
This commit is contained in:
parent
4c656cdbf9
commit
a2c6a71b4d
6 changed files with 19 additions and 2000 deletions
5
HOWTO.md
5
HOWTO.md
|
|
@ -13,3 +13,8 @@
|
||||||
## List Authors
|
## List Authors
|
||||||
|
|
||||||
`git log --format='%aN' | sort -u`
|
`git log --format='%aN' | sort -u`
|
||||||
|
|
||||||
|
## Subtree
|
||||||
|
|
||||||
|
If gen is [this remote](https://github.com/c-cube/gen.git):
|
||||||
|
`git subtree pull --prefix gen gen master --squash`
|
||||||
|
|
|
||||||
2
_oasis
2
_oasis
|
|
@ -43,7 +43,7 @@ Flag "bench"
|
||||||
|
|
||||||
Library "containers"
|
Library "containers"
|
||||||
Path: core
|
Path: core
|
||||||
Modules: CCVector, CCDeque, CCGen, CCSequence, CCFQueue, CCMultiMap,
|
Modules: CCVector, CCDeque, CCGen, Gen_intf, CCSequence, CCFQueue, CCMultiMap,
|
||||||
CCMultiSet, CCBV, CCPrint, CCPersistentHashtbl, CCError,
|
CCMultiSet, CCBV, CCPrint, CCPersistentHashtbl, CCError,
|
||||||
CCHeap, CCList, CCOpt, CCPair, CCFun, CCHash,
|
CCHeap, CCList, CCOpt, CCPair, CCFun, CCHash,
|
||||||
CCKList, CCInt, CCBool, CCFloat, CCArray, CCOrd, CCIO,
|
CCKList, CCInt, CCBool, CCFloat, CCArray, CCOrd, CCIO,
|
||||||
|
|
|
||||||
1
_tags
1
_tags
|
|
@ -160,5 +160,6 @@
|
||||||
<tests/*.ml{,i}>: thread
|
<tests/*.ml{,i}>: thread
|
||||||
<threads/*.ml{,i}>: thread
|
<threads/*.ml{,i}>: thread
|
||||||
<sequence>: -traverse
|
<sequence>: -traverse
|
||||||
|
<gen>: -traverse
|
||||||
<core/CCVector.cmx>: inline(25)
|
<core/CCVector.cmx>: inline(25)
|
||||||
<{string,core}/**/*.ml>: warn_A, warn(-4), warn(-44)
|
<{string,core}/**/*.ml>: warn_A, warn(-4), warn(-44)
|
||||||
|
|
|
||||||
1716
core/CCGen.ml
1716
core/CCGen.ml
File diff suppressed because it is too large
Load diff
1
core/CCGen.ml
Symbolic link
1
core/CCGen.ml
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../gen/gen.ml
|
||||||
293
core/CCGen.mli
293
core/CCGen.mli
|
|
@ -43,289 +43,10 @@ type 'a t = unit -> 'a option
|
||||||
|
|
||||||
type 'a gen = 'a t
|
type 'a gen = 'a t
|
||||||
|
|
||||||
(** {2 Common signature for transient and restartable generators}
|
(** {b NOTE}: version informations ("@since" annotations) in CCGen_intf
|
||||||
|
will not be reliable, for they will represent versions of Gen
|
||||||
The signature {!S} abstracts on a type ['a t], where the [t] can be
|
rather than containers. *)
|
||||||
the type of transient or restartable generators. Some functions specify
|
module type S = Gen_intf.S
|
||||||
explicitely that they use ['a gen] (transient generators). *)
|
|
||||||
|
|
||||||
module type S = sig
|
|
||||||
type 'a t
|
|
||||||
|
|
||||||
val empty : 'a t
|
|
||||||
(** Empty generator, with no elements *)
|
|
||||||
|
|
||||||
val singleton : 'a -> 'a t
|
|
||||||
(** One-element generator *)
|
|
||||||
|
|
||||||
val repeat : 'a -> 'a t
|
|
||||||
(** Repeat same element endlessly *)
|
|
||||||
|
|
||||||
val iterate : 'a -> ('a -> 'a) -> 'a t
|
|
||||||
(** [iterate x f] is [[x; f x; f (f x); f (f (f x)); ...]] *)
|
|
||||||
|
|
||||||
val unfold : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
|
||||||
(** Dual of {!fold}, with a deconstructing operation. It keeps on
|
|
||||||
unfolding the ['b] value into a new ['b], and a ['a] which is yielded,
|
|
||||||
until [None] is returned. *)
|
|
||||||
|
|
||||||
val init : ?limit:int -> (int -> 'a) -> 'a t
|
|
||||||
(** Calls the function, starting from 0, on increasing indices.
|
|
||||||
If [limit] is provided and is a positive int, iteration will
|
|
||||||
stop at the limit (excluded).
|
|
||||||
For instance [init ~limit:4 id] will yield 0, 1, 2, and 3. *)
|
|
||||||
|
|
||||||
(** {2 Basic combinators} *)
|
|
||||||
|
|
||||||
val is_empty : _ t -> bool
|
|
||||||
(** Check whether the genertor is empty. Consumes one element if the
|
|
||||||
generator isn't empty. *)
|
|
||||||
|
|
||||||
val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
|
||||||
(** Fold on the generator, tail-recursively; consumes it *)
|
|
||||||
|
|
||||||
val reduce : ('a -> 'a -> 'a) -> 'a t -> 'a
|
|
||||||
(** Fold on non-empty sequences
|
|
||||||
@raise Invalid_argument if the generator is empty *)
|
|
||||||
|
|
||||||
val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t
|
|
||||||
(** Like {!fold}, but keeping successive values of the accumulator *)
|
|
||||||
|
|
||||||
val iter : ('a -> unit) -> 'a t -> unit
|
|
||||||
(** Iterate on the generator, consuming it *)
|
|
||||||
|
|
||||||
val iteri : (int -> 'a -> unit) -> 'a t -> unit
|
|
||||||
(** Iterate on elements with their index in the enum, from 0. Consumes it. *)
|
|
||||||
|
|
||||||
val length : _ t -> int
|
|
||||||
(** Length of a generator (linear time, consumes its input) *)
|
|
||||||
|
|
||||||
val map : ('a -> 'b) -> 'a t -> 'b t
|
|
||||||
(** Lazy map. No iteration is performed now, the function will be called
|
|
||||||
when the result is traversed. *)
|
|
||||||
|
|
||||||
val append : 'a t -> 'a t -> 'a t
|
|
||||||
(** Append the two enums; the result contains the elements of the first,
|
|
||||||
then the elements of the second enum. *)
|
|
||||||
|
|
||||||
val flatten : 'a gen t -> 'a t
|
|
||||||
(** Flatten the enumeration of generators *)
|
|
||||||
|
|
||||||
val flat_map : ('a -> 'b gen) -> 'a t -> 'b t
|
|
||||||
(** Monadic bind; each element is transformed to a sub-enum
|
|
||||||
which is then iterated on, before the next element is processed,
|
|
||||||
and so on. *)
|
|
||||||
|
|
||||||
val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool
|
|
||||||
(** Is the given element, member of the enum? *)
|
|
||||||
|
|
||||||
val take : int -> 'a t -> 'a t
|
|
||||||
(** Take at most n elements *)
|
|
||||||
|
|
||||||
val drop : int -> 'a t -> 'a t
|
|
||||||
(** Drop n elements *)
|
|
||||||
|
|
||||||
val nth : int -> 'a t -> 'a
|
|
||||||
(** n-th element, or Not_found
|
|
||||||
@raise Not_found if the generator contains less than [n] arguments *)
|
|
||||||
|
|
||||||
val take_nth : int -> 'a t -> 'a t
|
|
||||||
(** [take_nth n g] returns every element of [g] whose index
|
|
||||||
is a multiple of [n]. For instance [take_nth 2 (1--10) |> to_list]
|
|
||||||
will return [1;3;5;7;9] *)
|
|
||||||
|
|
||||||
val filter : ('a -> bool) -> 'a t -> 'a t
|
|
||||||
(** Filter out elements that do not satisfy the predicate. *)
|
|
||||||
|
|
||||||
val take_while : ('a -> bool) -> 'a t -> 'a t
|
|
||||||
(** Take elements while they satisfy the predicate *)
|
|
||||||
|
|
||||||
val drop_while : ('a -> bool) -> 'a t -> 'a t
|
|
||||||
(** Drop elements while they satisfy the predicate *)
|
|
||||||
|
|
||||||
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
|
|
||||||
(** Maps some elements to 'b, drop the other ones *)
|
|
||||||
|
|
||||||
val zip_index : 'a t -> (int * 'a) t
|
|
||||||
(** Zip elements with their index in the enum *)
|
|
||||||
|
|
||||||
val unzip : ('a * 'b) t -> 'a t * 'b t
|
|
||||||
(** Unzip into two sequences, splitting each pair *)
|
|
||||||
|
|
||||||
val partition : ('a -> bool) -> 'a t -> 'a t * 'a t
|
|
||||||
(** [partition p l] returns the elements that satisfy [p],
|
|
||||||
and the elements that do not satisfy [p] *)
|
|
||||||
|
|
||||||
val for_all : ('a -> bool) -> 'a t -> bool
|
|
||||||
(** Is the predicate true for all elements? *)
|
|
||||||
|
|
||||||
val exists : ('a -> bool) -> 'a t -> bool
|
|
||||||
(** Is the predicate true for at least one element? *)
|
|
||||||
|
|
||||||
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a
|
|
||||||
(** Minimum element, according to the given comparison function.
|
|
||||||
@raise Invalid_argument if the generator is empty *)
|
|
||||||
|
|
||||||
val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a
|
|
||||||
(** Maximum element, see {!min}
|
|
||||||
@raise Invalid_argument if the generator is empty *)
|
|
||||||
|
|
||||||
val eq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
|
||||||
(** Equality of generators. *)
|
|
||||||
|
|
||||||
val lexico : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t -> int
|
|
||||||
(** Lexicographic comparison of generators. If a generator is a prefix
|
|
||||||
of the other one, it is considered smaller. *)
|
|
||||||
|
|
||||||
val compare : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t -> int
|
|
||||||
(** Synonym for {! lexico} *)
|
|
||||||
|
|
||||||
val find : ('a -> bool) -> 'a t -> 'a option
|
|
||||||
(** [find p e] returns the first element of [e] to satisfy [p],
|
|
||||||
or None. *)
|
|
||||||
|
|
||||||
val sum : int t -> int
|
|
||||||
(** Sum of all elements *)
|
|
||||||
|
|
||||||
(** {2 Multiple iterators} *)
|
|
||||||
|
|
||||||
val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
|
||||||
(** Map on the two sequences. Stops once one of them is exhausted.*)
|
|
||||||
|
|
||||||
val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
|
||||||
(** Iterate on the two sequences. Stops once one of them is exhausted.*)
|
|
||||||
|
|
||||||
val fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc
|
|
||||||
(** Fold the common prefix of the two iterators *)
|
|
||||||
|
|
||||||
val for_all2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
|
||||||
(** Succeeds if all pairs of elements satisfy the predicate.
|
|
||||||
Ignores elements of an iterator if the other runs dry. *)
|
|
||||||
|
|
||||||
val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
|
||||||
(** Succeeds if some pair of elements satisfy the predicate.
|
|
||||||
Ignores elements of an iterator if the other runs dry. *)
|
|
||||||
|
|
||||||
val zip_with : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
|
||||||
(** Combine common part of the enums (stops when one is exhausted) *)
|
|
||||||
|
|
||||||
val zip : 'a t -> 'b t -> ('a * 'b) t
|
|
||||||
(** Zip together the common part of the enums *)
|
|
||||||
|
|
||||||
(** {2 Complex combinators} *)
|
|
||||||
|
|
||||||
val merge : 'a gen t -> 'a t
|
|
||||||
(** Pick elements fairly in each sub-generator. The merge of enums
|
|
||||||
[e1, e2, ... ] picks elements in [e1], [e2],
|
|
||||||
in [e3], [e1], [e2] .... Once a generator is empty, it is skipped;
|
|
||||||
when they are all empty, and none remains in the input,
|
|
||||||
their merge is also empty.
|
|
||||||
For instance, [merge [1;3;5] [2;4;6]] will be, in disorder, [1;2;3;4;5;6]. *)
|
|
||||||
|
|
||||||
val intersection : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t -> 'a t
|
|
||||||
(** Intersection of two sorted sequences. Only elements that occur in both
|
|
||||||
inputs appear in the output *)
|
|
||||||
|
|
||||||
val sorted_merge : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t -> 'a t
|
|
||||||
(** Merge two sorted sequences into a sorted sequence *)
|
|
||||||
|
|
||||||
val sorted_merge_n : ?cmp:('a -> 'a -> int) -> 'a t list -> 'a t
|
|
||||||
(** Sorted merge of multiple sorted sequences *)
|
|
||||||
|
|
||||||
val tee : ?n:int -> 'a t -> 'a gen list
|
|
||||||
(** Duplicate the enum into [n] generators (default 2). The generators
|
|
||||||
share the same underlying instance of the enum, so the optimal case is
|
|
||||||
when they are consumed evenly *)
|
|
||||||
|
|
||||||
val round_robin : ?n:int -> 'a t -> 'a gen list
|
|
||||||
(** Split the enum into [n] generators in a fair way. Elements with
|
|
||||||
[index = k mod n] with go to the k-th enum. [n] default value
|
|
||||||
is 2. *)
|
|
||||||
|
|
||||||
val interleave : 'a t -> 'a t -> 'a t
|
|
||||||
(** [interleave a b] yields an element of [a], then an element of [b],
|
|
||||||
and so on. When a generator is exhausted, this behaves like the
|
|
||||||
other generator. *)
|
|
||||||
|
|
||||||
val intersperse : 'a -> 'a t -> 'a t
|
|
||||||
(** Put the separator element between all elements of the given enum *)
|
|
||||||
|
|
||||||
val product : 'a t -> 'b t -> ('a * 'b) t
|
|
||||||
(** Cartesian product, in no predictable order. Works even if some of the
|
|
||||||
arguments are infinite. *)
|
|
||||||
|
|
||||||
val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
|
|
||||||
(** Group equal consecutive elements together. *)
|
|
||||||
|
|
||||||
val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
|
|
||||||
(** Remove consecutive duplicate elements. Basically this is
|
|
||||||
like [fun e -> map List.hd (group e)]. *)
|
|
||||||
|
|
||||||
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
|
||||||
(** Sort according to the given comparison function. The enum must be finite. *)
|
|
||||||
|
|
||||||
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
|
||||||
(** Sort and remove duplicates. The enum must be finite. *)
|
|
||||||
|
|
||||||
val chunks : int -> 'a t -> 'a array t
|
|
||||||
(** [chunks n e] returns a generator of arrays of length [n], composed
|
|
||||||
of successive elements of [e]. The last array may be smaller
|
|
||||||
than [n] *)
|
|
||||||
|
|
||||||
(* TODO later
|
|
||||||
val permutations : 'a t -> 'a gen t
|
|
||||||
(** Permutations of the enum. Each permutation becomes unavailable once
|
|
||||||
the next one is produced. *)
|
|
||||||
|
|
||||||
val combinations : int -> 'a t -> 'a t t
|
|
||||||
(** Combinations of given length. *)
|
|
||||||
|
|
||||||
val powerSet : 'a t -> 'a t t
|
|
||||||
(** All subsets of the enum (in no particular order) *)
|
|
||||||
*)
|
|
||||||
|
|
||||||
(** {2 Basic conversion functions} *)
|
|
||||||
|
|
||||||
val of_list : 'a list -> 'a t
|
|
||||||
(** Enumerate elements of the list *)
|
|
||||||
|
|
||||||
val to_list : 'a t -> 'a list
|
|
||||||
(** non tail-call trasnformation to list, in the same order *)
|
|
||||||
|
|
||||||
val to_rev_list : 'a t -> 'a list
|
|
||||||
(** Tail call conversion to list, in reverse order (more efficient) *)
|
|
||||||
|
|
||||||
val to_array : 'a t -> 'a array
|
|
||||||
(** Convert the enum to an array (not very efficient) *)
|
|
||||||
|
|
||||||
val of_array : ?start:int -> ?len:int -> 'a array -> 'a t
|
|
||||||
(** Iterate on (a slice of) the given array *)
|
|
||||||
|
|
||||||
val rand_int : int -> int t
|
|
||||||
(** Random ints in the given range. *)
|
|
||||||
|
|
||||||
val int_range : int -> int -> int t
|
|
||||||
(** [int_range a b] enumerates integers between [a] and [b], included. [a]
|
|
||||||
is assumed to be smaller than [b]. *)
|
|
||||||
|
|
||||||
module Infix : sig
|
|
||||||
val (--) : int -> int -> int t
|
|
||||||
(** Synonym for {! int_range} *)
|
|
||||||
|
|
||||||
val (>>=) : 'a t -> ('a -> 'b gen) -> 'b t
|
|
||||||
(** Monadic bind operator *)
|
|
||||||
end
|
|
||||||
|
|
||||||
val (--) : int -> int -> int t
|
|
||||||
(** Synonym for {! int_range} *)
|
|
||||||
|
|
||||||
val (>>=) : 'a t -> ('a -> 'b gen) -> 'b t
|
|
||||||
(** Monadic bind operator *)
|
|
||||||
|
|
||||||
val pp : ?start:string -> ?stop:string -> ?sep:string -> ?horizontal:bool ->
|
|
||||||
(Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
|
|
||||||
(** Pretty print the content of the generator on a formatter. *)
|
|
||||||
end
|
|
||||||
|
|
||||||
(** {2 Transient generators} *)
|
(** {2 Transient generators} *)
|
||||||
|
|
||||||
|
|
@ -373,6 +94,12 @@ val persistent : 'a t -> 'a Restart.t
|
||||||
on it several times later. If possible, consider using combinators
|
on it several times later. If possible, consider using combinators
|
||||||
from {!Restart} directly instead. *)
|
from {!Restart} directly instead. *)
|
||||||
|
|
||||||
|
val persistent_lazy : 'a t -> 'a Restart.t
|
||||||
|
(** Same as {!persistent}, but consumes the generator on demand (by chunks).
|
||||||
|
This allows to make a restartable generator out of an ephemeral one,
|
||||||
|
without paying a big cost upfront (nor even consuming it fully).
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val start : 'a Restart.t -> 'a t
|
val start : 'a Restart.t -> 'a t
|
||||||
(** Create a new transient generator.
|
(** Create a new transient generator.
|
||||||
[start gen] is the same as [gen ()] but is included for readability. *)
|
[start gen] is the same as [gen ()] but is included for readability. *)
|
||||||
|
|
|
||||||
1
core/Gen_intf.ml
Symbolic link
1
core/Gen_intf.ml
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../gen/gen_intf.ml
|
||||||
Loading…
Add table
Reference in a new issue