mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 03:05:28 -05:00
updated and fixed things in core/:
fixed warnings, updated Sequence/Gen with tests and more recent interface; added printers
This commit is contained in:
parent
2dc743965b
commit
113ea6d395
11 changed files with 613 additions and 340 deletions
466
core/CCGen.ml
466
core/CCGen.ml
|
|
@ -67,10 +67,6 @@ module type S = sig
|
|||
val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
||||
(** Fold on the generator, tail-recursively *)
|
||||
|
||||
val fold2 : ('c -> 'a -> 'b -> 'c) -> 'c -> 'a t -> 'b t -> 'c
|
||||
(** Fold on the two enums in parallel. Stops once one of the enums
|
||||
is exhausted. *)
|
||||
|
||||
val reduce : ('a -> 'a -> 'a) -> 'a t -> 'a
|
||||
(** Fold on non-empty sequences (otherwise raise Invalid_argument) *)
|
||||
|
||||
|
|
@ -83,9 +79,6 @@ module type S = sig
|
|||
val iteri : (int -> 'a -> unit) -> 'a t -> unit
|
||||
(** Iterate on elements with their index in the enum, from 0 *)
|
||||
|
||||
val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
||||
(** Iterate on the two sequences. Stops once one of them is exhausted.*)
|
||||
|
||||
val length : _ t -> int
|
||||
(** Length of an enum (linear time) *)
|
||||
|
||||
|
|
@ -100,7 +93,7 @@ module type S = sig
|
|||
val flatten : 'a gen t -> 'a t
|
||||
(** Flatten the enumeration of generators *)
|
||||
|
||||
val flatMap : ('a -> 'b gen) -> 'a t -> 'b t
|
||||
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. *)
|
||||
|
|
@ -118,19 +111,24 @@ module type S = sig
|
|||
(** 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 takeWhile : ('a -> bool) -> 'a t -> 'a t
|
||||
val take_while : ('a -> bool) -> 'a t -> 'a t
|
||||
(** Take elements while they satisfy the predicate *)
|
||||
|
||||
val dropWhile : ('a -> bool) -> 'a t -> 'a t
|
||||
val drop_while : ('a -> bool) -> 'a t -> 'a t
|
||||
(** Drop elements while they satisfy the predicate *)
|
||||
|
||||
val filterMap : ('a -> 'b option) -> 'a t -> 'b t
|
||||
(** Maps some elements to 'b, drop the other ones *)
|
||||
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
|
||||
(** _maps some elements to 'b, drop the other ones *)
|
||||
|
||||
val zipIndex : 'a t -> (int * 'a) t
|
||||
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
|
||||
|
|
@ -174,10 +172,13 @@ module type S = sig
|
|||
(** {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.
|
||||
|
|
@ -187,7 +188,7 @@ module type S = sig
|
|||
(** Succeeds if some pair of elements satisfy the predicate.
|
||||
Ignores elements of an iterator if the other runs dry. *)
|
||||
|
||||
val zipWith : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
||||
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
|
||||
|
|
@ -312,15 +313,33 @@ end
|
|||
|
||||
let empty () = None
|
||||
|
||||
(*$T empty
|
||||
empty |> to_list = []
|
||||
*)
|
||||
|
||||
let singleton x =
|
||||
let first = ref true in
|
||||
fun () ->
|
||||
if !first then (first := false; Some x) else None
|
||||
|
||||
let rec repeat x () = Some x
|
||||
(*T singleton
|
||||
singleton 1 |> to_list = [1]
|
||||
singleton "foo" |> to_list = ["foo"]
|
||||
*)
|
||||
|
||||
let repeat x () = Some x
|
||||
|
||||
(*$T repeat
|
||||
repeat 42 |> take 3 |> to_list = [42; 42; 42]
|
||||
*)
|
||||
|
||||
let repeatedly f () = Some (f ())
|
||||
|
||||
(*$T repeatedly
|
||||
repeatedly (let r = ref 0 in fun () -> incr r; !r) \
|
||||
|> take 5 |> to_list = [1;2;3;4;5]
|
||||
*)
|
||||
|
||||
let iterate x f =
|
||||
let cur = ref x in
|
||||
fun () ->
|
||||
|
|
@ -328,6 +347,10 @@ let iterate x f =
|
|||
cur := f !cur;
|
||||
Some x
|
||||
|
||||
(*$T iterate
|
||||
iterate 0 ((+)1) |> take 5 |> to_list = [0;1;2;3;4]
|
||||
*)
|
||||
|
||||
let next gen = gen ()
|
||||
|
||||
let get gen = gen ()
|
||||
|
|
@ -337,6 +360,14 @@ let get_exn gen =
|
|||
| Some x -> x
|
||||
| None -> raise (Invalid_argument "Gen.get_exn")
|
||||
|
||||
(*$R get_exn
|
||||
let g = of_list [1;2;3] in
|
||||
assert_equal 1 (get_exn g);
|
||||
assert_equal 2 (get_exn g);
|
||||
assert_equal 3 (get_exn g);
|
||||
assert_raises (Invalid_argument "Gen.get_exn") (fun () -> get_exn g)
|
||||
*)
|
||||
|
||||
let junk gen = ignore (gen ())
|
||||
|
||||
let rec fold f acc gen =
|
||||
|
|
@ -344,6 +375,11 @@ let rec fold f acc gen =
|
|||
| None -> acc
|
||||
| Some x -> fold f (f acc x) gen
|
||||
|
||||
(*$Q
|
||||
(Q.list Q.small_int) (fun l -> \
|
||||
of_list l |> fold (fun l x->x::l) [] = List.rev l)
|
||||
*)
|
||||
|
||||
let reduce f g =
|
||||
let acc = match g () with
|
||||
| None -> raise (Invalid_argument "reduce")
|
||||
|
|
@ -361,6 +397,11 @@ let unfold f acc =
|
|||
acc := acc';
|
||||
Some x
|
||||
|
||||
(*$T unfold
|
||||
unfold (fun (prev,cur) -> Some (prev, (cur,prev+cur))) (0,1) \
|
||||
|> take 7 |> to_list = [0; 1; 1; 2; 3; 5; 8]
|
||||
*)
|
||||
|
||||
let init ?(limit=max_int) f =
|
||||
let r = ref 0 in
|
||||
fun () ->
|
||||
|
|
@ -371,6 +412,10 @@ let init ?(limit=max_int) f =
|
|||
let _ = incr r in
|
||||
Some x
|
||||
|
||||
(*$T init
|
||||
init ~limit:5 (fun i->i) |> to_list = [0;1;2;3;4]
|
||||
*)
|
||||
|
||||
let rec iter f gen =
|
||||
match gen() with
|
||||
| None -> ()
|
||||
|
|
@ -387,9 +432,19 @@ let is_empty gen = match gen () with
|
|||
| None -> true
|
||||
| Some _ -> false
|
||||
|
||||
(*$T
|
||||
is_empty empty
|
||||
not (is_empty (singleton 2))
|
||||
*)
|
||||
|
||||
let length gen =
|
||||
fold (fun acc _ -> acc + 1) 0 gen
|
||||
|
||||
(*$Q
|
||||
(Q.list Q.small_int) (fun l -> \
|
||||
of_list l |> length = List.length l)
|
||||
*)
|
||||
|
||||
(* useful state *)
|
||||
type 'a run_state =
|
||||
| Init
|
||||
|
|
@ -412,10 +467,10 @@ let scan f acc g =
|
|||
state := Run acc';
|
||||
Some acc'
|
||||
|
||||
let rec iter2 f gen1 gen2 =
|
||||
match gen1(), gen2() with
|
||||
| Some x, Some y -> f x y; iter2 f gen1 gen2
|
||||
| _ -> ()
|
||||
(*$T scan
|
||||
scan (fun acc x -> x+1::acc) [] (1--5) |> to_list \
|
||||
= [[]; [2]; [3;2]; [4;3;2]; [5;4;3;2]; [6;5;4;3;2]]
|
||||
*)
|
||||
|
||||
(** {3 Lazy} *)
|
||||
|
||||
|
|
@ -427,6 +482,12 @@ let map f gen =
|
|||
| None -> stop:= true; None
|
||||
| Some x -> Some (f x)
|
||||
|
||||
(*$Q map
|
||||
(Q.list Q.small_int) (fun l -> \
|
||||
let f x = x*2 in \
|
||||
of_list l |> map f |> to_list = List.map f l)
|
||||
*)
|
||||
|
||||
let append gen1 gen2 =
|
||||
let first = ref true in
|
||||
let rec next() =
|
||||
|
|
@ -437,6 +498,11 @@ let append gen1 gen2 =
|
|||
else gen2()
|
||||
in next
|
||||
|
||||
(*$Q
|
||||
(Q.pair (Q.list Q.small_int)(Q.list Q.small_int)) (fun (l1,l2) -> \
|
||||
append (of_list l1) (of_list l2) |> to_list = l1 @ l2)
|
||||
*)
|
||||
|
||||
let flatten next_gen =
|
||||
let state = ref Init in
|
||||
(* get next element *)
|
||||
|
|
@ -455,7 +521,7 @@ let flatten next_gen =
|
|||
in
|
||||
next
|
||||
|
||||
let flatMap f next_elem =
|
||||
let flat_map f next_elem =
|
||||
let state = ref Init in
|
||||
let rec next() =
|
||||
match !state with
|
||||
|
|
@ -474,6 +540,12 @@ let flatMap f next_elem =
|
|||
in
|
||||
next
|
||||
|
||||
(*$Q flat_map
|
||||
(Q.list Q.small_int) (fun l -> \
|
||||
let f x = of_list [x;x*2] in \
|
||||
eq (map f (of_list l) |> flatten) (flat_map f (of_list l)))
|
||||
*)
|
||||
|
||||
let mem ?(eq=(=)) x gen =
|
||||
let rec mem eq x gen =
|
||||
match gen() with
|
||||
|
|
@ -491,6 +563,11 @@ let take n gen =
|
|||
| None -> count := ~-1; None (* indicate stop *)
|
||||
| (Some _) as x -> incr count; x
|
||||
|
||||
(*$Q
|
||||
(Q.pair Q.small_int (Q.list Q.small_int)) (fun (n,l) -> \
|
||||
of_list l |> take n |> length = Pervasives.min n (List.length l))
|
||||
*)
|
||||
|
||||
(* call [gen] at most [n] times, and stop *)
|
||||
let rec __drop n gen =
|
||||
if n = 0 then ()
|
||||
|
|
@ -511,6 +588,12 @@ let drop n gen =
|
|||
gen()
|
||||
end
|
||||
|
||||
(*$Q
|
||||
(Q.pair Q.small_int (Q.list Q.small_int)) (fun (n,l) -> \
|
||||
let g1,g2 = take n (of_list l), drop n (of_list l) in \
|
||||
append g1 g2 |> to_list = l)
|
||||
*)
|
||||
|
||||
let nth n gen =
|
||||
assert (n>=0);
|
||||
__drop n gen;
|
||||
|
|
@ -518,6 +601,25 @@ let nth n gen =
|
|||
| None -> raise Not_found
|
||||
| Some x -> x
|
||||
|
||||
(*$= nth & ~printer:string_of_int
|
||||
4 (nth 4 (0--10))
|
||||
8 (nth 8 (0--10))
|
||||
*)
|
||||
|
||||
(*$T
|
||||
(try ignore (nth 11 (1--10)); false with Not_found -> true)
|
||||
*)
|
||||
|
||||
let take_nth n gen =
|
||||
assert (n>=1);
|
||||
let i = ref n in
|
||||
let rec next() =
|
||||
match gen() with
|
||||
| None -> None
|
||||
| (Some _) as res when !i = n -> i:=1; res
|
||||
| Some _ -> incr i; next()
|
||||
in next
|
||||
|
||||
let filter p gen =
|
||||
let rec next () =
|
||||
(* wrap exception into option, for next to be tailrec *)
|
||||
|
|
@ -529,16 +631,23 @@ let filter p gen =
|
|||
else next () (* discard element *)
|
||||
in next
|
||||
|
||||
let takeWhile p gen =
|
||||
(*$T
|
||||
filter (fun x ->x mod 2 = 0) (1--10) |> to_list = [2;4;6;8;10]
|
||||
*)
|
||||
|
||||
let take_while p gen =
|
||||
let stop = ref false in
|
||||
let rec next () =
|
||||
fun () ->
|
||||
if !stop
|
||||
then None
|
||||
else match gen() with
|
||||
| (Some x) as res ->
|
||||
if p x then res else (stop := true; None)
|
||||
| None -> stop:=true; None
|
||||
in next
|
||||
|
||||
(*$T
|
||||
take_while (fun x ->x<10) (1--1000) |> eq (1--9)
|
||||
*)
|
||||
|
||||
module DropWhileState = struct
|
||||
type t =
|
||||
|
|
@ -547,9 +656,9 @@ module DropWhileState = struct
|
|||
| Yield
|
||||
end
|
||||
|
||||
let dropWhile p gen =
|
||||
let drop_while p gen =
|
||||
let open DropWhileState in
|
||||
let state = ref Stop in
|
||||
let state = ref Drop in
|
||||
let rec next () =
|
||||
match !state with
|
||||
| Stop -> None
|
||||
|
|
@ -566,7 +675,11 @@ let dropWhile p gen =
|
|||
end
|
||||
in next
|
||||
|
||||
let filterMap f gen =
|
||||
(*$T
|
||||
drop_while (fun x-> x<10) (1--20) |> eq (10--20)
|
||||
*)
|
||||
|
||||
let filter_map f gen =
|
||||
(* tailrec *)
|
||||
let rec next () =
|
||||
match gen() with
|
||||
|
|
@ -577,7 +690,12 @@ let filterMap f gen =
|
|||
| (Some _) as res -> res
|
||||
in next
|
||||
|
||||
let zipIndex gen =
|
||||
(*$T
|
||||
filter_map (fun x-> if x mod 2 = 0 then Some (string_of_int x) else None) (1--10) \
|
||||
|> to_list = List.map string_of_int [2;4;6;8;10]
|
||||
*)
|
||||
|
||||
let zip_index gen =
|
||||
let r = ref ~-1 in
|
||||
fun () ->
|
||||
match gen() with
|
||||
|
|
@ -586,6 +704,10 @@ let zipIndex gen =
|
|||
incr r;
|
||||
Some (!r, x)
|
||||
|
||||
(*$T
|
||||
zip_index (1--5) |> to_list = [0,1; 1,2; 2,3; 3,4; 4,5]
|
||||
*)
|
||||
|
||||
let unzip gen =
|
||||
let stop = ref false in
|
||||
let q1 = Queue.create () in
|
||||
|
|
@ -612,6 +734,17 @@ let unzip gen =
|
|||
in
|
||||
next_left, next_right
|
||||
|
||||
(*$T
|
||||
unzip (of_list [1,2;3,4]) |> (fun (x,y)-> to_list x, to_list y) \
|
||||
= ([1;3], [2;4])
|
||||
*)
|
||||
|
||||
(*$Q
|
||||
(Q.list (Q.pair Q.small_int Q.small_int)) (fun l -> \
|
||||
of_list l |> unzip |> (fun (x,y) -> to_list x,to_list y) = \
|
||||
List.split l)
|
||||
*)
|
||||
|
||||
(* [partition p l] returns the elements that satisfy [p],
|
||||
and the elements that do not satisfy [p] *)
|
||||
let partition p gen =
|
||||
|
|
@ -637,6 +770,11 @@ let partition p gen =
|
|||
in
|
||||
nexttrue, nextfalse
|
||||
|
||||
(*$T
|
||||
partition (fun x -> x mod 2 = 0) (1--10) |> \
|
||||
(fun (x,y)->to_list x, to_list y) = ([2;4;6;8;10], [1;3;5;7;9])
|
||||
*)
|
||||
|
||||
let rec for_all p gen =
|
||||
match gen() with
|
||||
| None -> true
|
||||
|
|
@ -654,6 +792,11 @@ let min ?(lt=fun x y -> x < y) gen =
|
|||
in
|
||||
fold (fun min x -> if lt x min then x else min) first gen
|
||||
|
||||
(*$T
|
||||
min (of_list [1;4;6;0;11; -2]) = ~-2
|
||||
(try ignore (min empty); false with Invalid_argument _ -> true)
|
||||
*)
|
||||
|
||||
let max ?(lt=fun x y -> x < y) gen =
|
||||
let first = match gen () with
|
||||
| Some x -> x
|
||||
|
|
@ -661,6 +804,11 @@ let max ?(lt=fun x y -> x < y) gen =
|
|||
in
|
||||
fold (fun max x -> if lt max x then x else max) first gen
|
||||
|
||||
(*$T
|
||||
max (of_list [1;4;6;0;11; -2]) = 11
|
||||
(try ignore (max empty); false with Invalid_argument _ -> true)
|
||||
*)
|
||||
|
||||
let eq ?(eq=(=)) gen1 gen2 =
|
||||
let rec check () =
|
||||
match gen1(), gen2() with
|
||||
|
|
@ -670,6 +818,11 @@ let eq ?(eq=(=)) gen1 gen2 =
|
|||
in
|
||||
check ()
|
||||
|
||||
(*$Q
|
||||
(Q.pair (Q.list Q.small_int)(Q.list Q.small_int)) (fun (l1,l2) -> \
|
||||
eq (of_list l1)(of_list l2) = (l1 = l2))
|
||||
*)
|
||||
|
||||
let lexico ?(cmp=Pervasives.compare) gen1 gen2 =
|
||||
let rec lexico () =
|
||||
match gen1(), gen2() with
|
||||
|
|
@ -683,17 +836,32 @@ let lexico ?(cmp=Pervasives.compare) gen1 gen2 =
|
|||
|
||||
let compare ?cmp gen1 gen2 = lexico ?cmp gen1 gen2
|
||||
|
||||
(*$Q
|
||||
(Q.pair (Q.list Q.small_int)(Q.list Q.small_int)) (fun (l1,l2) -> \
|
||||
let sign x = if x < 0 then -1 else if x=0 then 0 else 1 in \
|
||||
sign (compare (of_list l1)(of_list l2)) = sign (Pervasives.compare l1 l2))
|
||||
*)
|
||||
|
||||
let rec find p e = match e () with
|
||||
| None -> None
|
||||
| Some x when p x -> Some x
|
||||
| Some _ -> find p e
|
||||
|
||||
(*$T
|
||||
find (fun x -> x>=5) (1--10) = Some 5
|
||||
find (fun x -> x>5) (1--4) = None
|
||||
*)
|
||||
|
||||
let sum e =
|
||||
let rec sum acc = match e() with
|
||||
| None -> acc
|
||||
| Some x -> sum (x+acc)
|
||||
in sum 0
|
||||
|
||||
(*$T
|
||||
sum (1--10) = 55
|
||||
*)
|
||||
|
||||
(** {2 Multiple Iterators} *)
|
||||
|
||||
let map2 f e1 e2 =
|
||||
|
|
@ -701,11 +869,20 @@ let map2 f e1 e2 =
|
|||
| Some x, Some y -> Some (f x y)
|
||||
| _ -> None
|
||||
|
||||
(*$T
|
||||
map2 (+) (1--5) (1--4) |> eq (of_list [2;4;6;8])
|
||||
map2 (+) (1--5) (repeat 0) |> eq (1--5)
|
||||
*)
|
||||
|
||||
let rec iter2 f e1 e2 =
|
||||
match e1(), e2() with
|
||||
| Some x, Some y -> f x y; iter2 f e1 e2
|
||||
| _ -> ()
|
||||
|
||||
(*$T iter2
|
||||
let r = ref 0 in iter2 (fun _ _ -> incr r) (1--10) (4--6); !r = 3
|
||||
*)
|
||||
|
||||
let rec fold2 f acc e1 e2 =
|
||||
match e1(), e2() with
|
||||
| Some x, Some y -> fold2 f (f acc x y) e1 e2
|
||||
|
|
@ -721,7 +898,7 @@ let rec exists2 p e1 e2 =
|
|||
| Some x, Some y -> p x y || exists2 p e1 e2
|
||||
| _ -> false
|
||||
|
||||
let zipWith f a b =
|
||||
let zip_with f a b =
|
||||
let stop = ref false in
|
||||
fun () ->
|
||||
if !stop then None
|
||||
|
|
@ -729,7 +906,13 @@ let zipWith f a b =
|
|||
| Some xa, Some xb -> Some (f xa xb)
|
||||
| _ -> stop:=true; None
|
||||
|
||||
let zip a b = zipWith (fun x y -> x,y) a b
|
||||
let zip a b = zip_with (fun x y -> x,y) a b
|
||||
|
||||
(*$Q
|
||||
(Q.list Q.small_int) (fun l -> \
|
||||
zip_with (fun x y->x,y) (of_list l) (of_list l) \
|
||||
|> unzip |> fst |> to_list = l)
|
||||
*)
|
||||
|
||||
(** {3 Complex combinators} *)
|
||||
|
||||
|
|
@ -746,7 +929,6 @@ module MergeState = struct
|
|||
| Stop
|
||||
end
|
||||
|
||||
(* TODO tests *)
|
||||
(* state machine:
|
||||
(NewGen -> YieldAndNew)* // then no more generators in next_gen, so
|
||||
-> Yield* -> Stop *)
|
||||
|
|
@ -792,6 +974,11 @@ let merge next_gen =
|
|||
end
|
||||
in next
|
||||
|
||||
(*$T
|
||||
merge (of_list [of_list [1;3;5]; of_list [2;4;6]; of_list [7;8;9]]) \
|
||||
|> to_list |> List.sort Pervasives.compare = [1;2;3;4;5;6;7;8;9]
|
||||
*)
|
||||
|
||||
let intersection ?(cmp=Pervasives.compare) gen1 gen2 =
|
||||
let x1 = ref (gen1 ()) in
|
||||
let x2 = ref (gen2 ()) in
|
||||
|
|
@ -808,6 +995,11 @@ let intersection ?(cmp=Pervasives.compare) gen1 gen2 =
|
|||
| _ -> None
|
||||
in next
|
||||
|
||||
(*$T
|
||||
intersection (of_list [1;1;2;3;4;8]) (of_list [1;2;4;5;6;7;8;9]) \
|
||||
|> to_list = [1;2;4;8]
|
||||
*)
|
||||
|
||||
let sorted_merge ?(cmp=Pervasives.compare) gen1 gen2 =
|
||||
let x1 = ref (gen1 ()) in
|
||||
let x2 = ref (gen2 ()) in
|
||||
|
|
@ -825,6 +1017,11 @@ let sorted_merge ?(cmp=Pervasives.compare) gen1 gen2 =
|
|||
x2 := gen2 ();
|
||||
r
|
||||
|
||||
(*$T
|
||||
sorted_merge (of_list [1;2;2;3;5;10;100]) (of_list [2;4;5;6;11]) \
|
||||
|> to_list = [1;2;2;2;3;4;5;5;6;10;11;100]
|
||||
*)
|
||||
|
||||
(** {4 Mutable heap (taken from heap.ml to avoid dependencies)} *)
|
||||
module Heap = struct
|
||||
type 'a t = {
|
||||
|
|
@ -884,6 +1081,11 @@ let sorted_merge_n ?(cmp=Pervasives.compare) l =
|
|||
| None -> Some x (* gen empty, drop it *)
|
||||
end
|
||||
|
||||
(*$T
|
||||
sorted_merge_n [of_list [1;2;2;3;5;10;100]; of_list [2;4;5;6;11]; (6--10)] \
|
||||
|> to_list = [1;2;2;2;3;4;5;5;6;6;7;8;9;10;10;11;100]
|
||||
*)
|
||||
|
||||
let round_robin ?(n=2) gen =
|
||||
(* array of queues, together with their index *)
|
||||
let qs = Array.init n (fun i -> Queue.create ()) in
|
||||
|
|
@ -916,6 +1118,11 @@ let round_robin ?(n=2) gen =
|
|||
let l = Array.mapi (fun i _ -> (fun () -> next i)) qs in
|
||||
Array.to_list l
|
||||
|
||||
(*$T
|
||||
round_robin ~n:3 (1--12) |> List.map to_list = \
|
||||
[[1;4;7;10]; [2;5;8;11]; [3;6;9;12]]
|
||||
*)
|
||||
|
||||
(* 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 *)
|
||||
|
|
@ -943,6 +1150,12 @@ let tee ?(n=2) gen =
|
|||
let l = Array.mapi (fun i _ -> (fun () -> next i)) qs in
|
||||
Array.to_list l
|
||||
|
||||
(*$T
|
||||
tee ~n:3 (1--12) |> List.map to_list = \
|
||||
[to_list (1--12); to_list (1--12); to_list (1--12)]
|
||||
*)
|
||||
|
||||
|
||||
module InterleaveState = struct
|
||||
type 'a t =
|
||||
| Only of 'a gen
|
||||
|
|
@ -971,6 +1184,11 @@ let interleave gen_a gen_b =
|
|||
res
|
||||
in next
|
||||
|
||||
(*$T
|
||||
interleave (repeat 0) (1--5) |> take 10 |> to_list = \
|
||||
[0;1;0;2;0;3;0;4;0;5]
|
||||
*)
|
||||
|
||||
module IntersperseState = struct
|
||||
type 'a t =
|
||||
| Start
|
||||
|
|
@ -1000,6 +1218,10 @@ let intersperse x gen =
|
|||
| Some _ as res -> state := YieldElem res; next()
|
||||
in next
|
||||
|
||||
(*$T
|
||||
intersperse 0 (1--5) |> to_list = [1;0;2;0;3;0;4;0;5]
|
||||
*)
|
||||
|
||||
(* Cartesian product *)
|
||||
let product gena genb =
|
||||
let all_a = ref [] in
|
||||
|
|
@ -1040,6 +1262,12 @@ let product gena genb =
|
|||
in
|
||||
next
|
||||
|
||||
(*$T
|
||||
product (1--3) (of_list ["a"; "b"]) |> to_list \
|
||||
|> List.sort Pervasives.compare = \
|
||||
[1, "a"; 1, "b"; 2, "a"; 2, "b"; 3, "a"; 3, "b"]
|
||||
*)
|
||||
|
||||
(* Group equal consecutive elements together. *)
|
||||
let group ?(eq=(=)) gen =
|
||||
match gen() with
|
||||
|
|
@ -1062,6 +1290,11 @@ let group ?(eq=(=)) gen =
|
|||
Some l
|
||||
in next
|
||||
|
||||
(*$T
|
||||
group (of_list [0;0;0;1;0;2;2;3;4;5;5;5;5;10]) |> to_list = \
|
||||
[[0;0;0];[1];[0];[2;2];[3];[4];[5;5;5;5];[10]]
|
||||
*)
|
||||
|
||||
let uniq ?(eq=(=)) gen =
|
||||
let state = ref Init in
|
||||
let rec next() = match !state with
|
||||
|
|
@ -1081,6 +1314,11 @@ let uniq ?(eq=(=)) gen =
|
|||
end
|
||||
in next
|
||||
|
||||
(*$T
|
||||
uniq (of_list [0;0;0;1;0;2;2;3;4;5;5;5;5;10]) |> to_list = \
|
||||
[0;1;0;2;3;4;5;10]
|
||||
*)
|
||||
|
||||
let sort ?(cmp=Pervasives.compare) gen =
|
||||
(* build heap *)
|
||||
let h = Heap.empty ~cmp in
|
||||
|
|
@ -1089,22 +1327,32 @@ let sort ?(cmp=Pervasives.compare) gen =
|
|||
if Heap.is_empty h
|
||||
then None
|
||||
else Some (Heap.pop h)
|
||||
(*$T
|
||||
sort (of_list [0;0;0;1;0;2;2;3;4;5;5;5;-42;5;10]) |> to_list = \
|
||||
[-42;0;0;0;0;1;2;2;3;4;5;5;5;5;10]
|
||||
*)
|
||||
|
||||
|
||||
(* NOTE: using a set is not really possible, because once we have built the
|
||||
set there is no simple way to iterate on it *)
|
||||
let sort_uniq ?(cmp=Pervasives.compare) gen =
|
||||
uniq ~eq:(fun x y -> cmp x y = 0) (sort ~cmp gen)
|
||||
|
||||
(*$T
|
||||
sort_uniq (of_list [0;0;0;1;0;2;2;3;4;5;42;5;5;42;5;10]) |> to_list = \
|
||||
[0;1;2;3;4;5;10;42]
|
||||
*)
|
||||
|
||||
let chunks n e =
|
||||
let rec next () =
|
||||
match e() with
|
||||
| None -> None
|
||||
| Some x ->
|
||||
let a = Array.make n x in
|
||||
fill a (n-1)
|
||||
fill a 1
|
||||
|
||||
and fill a i =
|
||||
(* fill the array. [i] elements remain to fill *)
|
||||
(* fill the array. [i]: current index to fill *)
|
||||
if i = n
|
||||
then Some a
|
||||
else match e() with
|
||||
|
|
@ -1115,6 +1363,11 @@ let chunks n e =
|
|||
in
|
||||
next
|
||||
|
||||
(*$T
|
||||
chunks 25 (0--100) |> map Array.to_list |> to_list = \
|
||||
List.map to_list [(0--24); (25--49);(50--74);(75--99);(100--100)]
|
||||
*)
|
||||
|
||||
(*
|
||||
let permutations enum =
|
||||
failwith "not implemented" (* TODO *)
|
||||
|
|
@ -1139,19 +1392,27 @@ let of_list l =
|
|||
let to_rev_list gen =
|
||||
fold (fun acc x -> x :: acc) [] gen
|
||||
|
||||
(*$Q
|
||||
(Q.list Q.small_int) (fun l -> \
|
||||
to_rev_list (of_list l) = List.rev l)
|
||||
*)
|
||||
|
||||
let to_list gen = List.rev (to_rev_list gen)
|
||||
|
||||
let to_array gen =
|
||||
let l = to_rev_list gen in
|
||||
let a = Array.of_list l in
|
||||
let n = Array.length a in
|
||||
(* reverse array *)
|
||||
for i = 0 to (n-1) / 2 do
|
||||
let tmp = a.(i) in
|
||||
a.(i) <- a.(n-i-1);
|
||||
a.(n-i-1) <- tmp
|
||||
done;
|
||||
a
|
||||
match l with
|
||||
| [] -> [| |]
|
||||
| _ ->
|
||||
let a = Array.of_list l in
|
||||
let n = Array.length a in
|
||||
(* reverse array *)
|
||||
for i = 0 to (n-1) / 2 do
|
||||
let tmp = a.(i) in
|
||||
a.(i) <- a.(n-i-1);
|
||||
a.(n-i-1) <- tmp
|
||||
done;
|
||||
a
|
||||
|
||||
let of_array ?(start=0) ?len a =
|
||||
let len = match len with
|
||||
|
|
@ -1163,6 +1424,11 @@ let of_array ?(start=0) ?len a =
|
|||
then None
|
||||
else (let x = a.(!i) in incr i; Some x)
|
||||
|
||||
(*$Q
|
||||
(Q.array Q.small_int) (fun a -> \
|
||||
of_array a |> to_array = a)
|
||||
*)
|
||||
|
||||
let rand_int i =
|
||||
repeatedly (fun () -> Random.int i)
|
||||
|
||||
|
|
@ -1200,7 +1466,7 @@ let pp ?(start="") ?(stop="") ?(sep=",") ?(horizontal=false) pp_elem formatter g
|
|||
module Infix = struct
|
||||
let (--) = int_range
|
||||
|
||||
let (>>=) x f = flatMap f x
|
||||
let (>>=) x f = flat_map f x
|
||||
end
|
||||
|
||||
include Infix
|
||||
|
|
@ -1221,8 +1487,6 @@ module Restart = struct
|
|||
|
||||
let repeat x () = repeat x
|
||||
|
||||
let repeatedly f () = repeatedly f
|
||||
|
||||
let unfold f acc () = unfold f acc
|
||||
|
||||
let init ?limit f () = init ?limit f
|
||||
|
|
@ -1257,7 +1521,7 @@ module Restart = struct
|
|||
|
||||
let flatten e () = flatten (e ())
|
||||
|
||||
let flatMap f e () = flatMap f (e ())
|
||||
let flat_map f e () = flat_map f (e ())
|
||||
|
||||
let mem ?eq x e = mem ?eq x (e ())
|
||||
|
||||
|
|
@ -1267,19 +1531,21 @@ module Restart = struct
|
|||
|
||||
let nth n e = nth n (e ())
|
||||
|
||||
let take_nth n e () = take_nth n (e ())
|
||||
|
||||
let filter p e () = filter p (e ())
|
||||
|
||||
let takeWhile p e () = takeWhile p (e ())
|
||||
let take_while p e () = take_while p (e ())
|
||||
|
||||
let dropWhile p e () = dropWhile p (e ())
|
||||
let drop_while p e () = drop_while p (e ())
|
||||
|
||||
let filterMap f e () = filterMap f (e ())
|
||||
let filter_map f e () = filter_map f (e ())
|
||||
|
||||
let zipWith f e1 e2 () = zipWith f (e1 ()) (e2 ())
|
||||
let zip_with f e1 e2 () = zip_with f (e1 ()) (e2 ())
|
||||
|
||||
let zip e1 e2 () = zip (e1 ()) (e2 ())
|
||||
|
||||
let zipIndex e () = zipIndex (e ())
|
||||
let zip_index e () = zip_index (e ())
|
||||
|
||||
let unzip e = map fst e, map snd e
|
||||
|
||||
|
|
@ -1373,7 +1639,7 @@ module Restart = struct
|
|||
module Infix = struct
|
||||
let (--) = int_range
|
||||
|
||||
let (>>=) x f = flatMap f x
|
||||
let (>>=) x f = flat_map f x
|
||||
end
|
||||
|
||||
include Infix
|
||||
|
|
@ -1386,53 +1652,65 @@ end
|
|||
|
||||
let start g = g ()
|
||||
|
||||
(** {4 Mutable double-linked list, similar to {! Deque.t} *)
|
||||
(** {6 Unrolled mutable list} *)
|
||||
module MList = struct
|
||||
type 'a t = 'a node option ref
|
||||
and 'a node = {
|
||||
content : 'a;
|
||||
mutable prev : 'a node;
|
||||
mutable next : 'a node;
|
||||
}
|
||||
type 'a node =
|
||||
| Nil
|
||||
| Cons of 'a array * int ref * 'a node ref
|
||||
|
||||
let create () = ref None
|
||||
let of_gen gen =
|
||||
let start = ref Nil in
|
||||
let chunk_size = ref 8 in
|
||||
(* fill the list. prev: tail-reference from previous node,
|
||||
* cur: current list node *)
|
||||
let rec fill prev cur =
|
||||
match cur, gen() with
|
||||
| _, None -> prev := cur; () (* done *)
|
||||
| Nil, Some x ->
|
||||
let n = !chunk_size in
|
||||
if n < 4096 then chunk_size := 2 * !chunk_size;
|
||||
fill prev (Cons (Array.make n x, ref 1, ref Nil))
|
||||
| Cons (a, n, next), Some x ->
|
||||
assert (!n < Array.length a);
|
||||
a.(!n) <- x;
|
||||
incr n;
|
||||
if !n = Array.length a
|
||||
then begin
|
||||
prev := cur;
|
||||
fill next Nil
|
||||
end else fill prev cur
|
||||
in
|
||||
fill start !start ;
|
||||
!start
|
||||
|
||||
let is_empty d =
|
||||
match !d with
|
||||
| None -> true
|
||||
| Some _ -> false
|
||||
|
||||
let push_back d x =
|
||||
match !d with
|
||||
| None ->
|
||||
let rec elt = {
|
||||
content = x; prev = elt; next = elt; } in
|
||||
d := Some elt
|
||||
| Some first ->
|
||||
let elt = { content = x; next=first; prev=first.prev; } in
|
||||
first.prev.next <- elt;
|
||||
first.prev <- elt
|
||||
|
||||
(* conversion to enum *)
|
||||
let to_enum d =
|
||||
fun () ->
|
||||
match !d with
|
||||
| None -> (fun () -> None)
|
||||
| Some first ->
|
||||
let cur = ref first in (* current element of the list *)
|
||||
let stop = ref false in (* are we done yet? *)
|
||||
fun () ->
|
||||
if !stop then None
|
||||
else begin
|
||||
let x = (!cur).content in
|
||||
cur := (!cur).next;
|
||||
(if !cur == first then stop := true); (* EOG, we made a full cycle *)
|
||||
Some x
|
||||
end
|
||||
let to_gen l () =
|
||||
let cur = ref l in
|
||||
let i = ref 0 in
|
||||
let rec next() = match !cur with
|
||||
| Nil -> None
|
||||
| Cons (a,n,l') ->
|
||||
if !i = !n
|
||||
then begin
|
||||
cur := !l';
|
||||
i := 0;
|
||||
next()
|
||||
end else begin
|
||||
let y = a.(!i) in
|
||||
incr i;
|
||||
Some y
|
||||
end
|
||||
in
|
||||
next
|
||||
end
|
||||
|
||||
(** Store content of the generator in an enum *)
|
||||
let persistent gen =
|
||||
let l = MList.create () in
|
||||
iter (MList.push_back l) gen;
|
||||
MList.to_enum l
|
||||
let l = MList.of_gen gen in
|
||||
MList.to_gen l
|
||||
|
||||
(*$T
|
||||
let g = 1--10 in let g' = persistent g in \
|
||||
Restart.to_list g' = Restart.to_list g'
|
||||
let g = 1--10 in let g' = persistent g in \
|
||||
Restart.to_list g' = [1;2;3;4;5;6;7;8;9;10]
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ module type S = sig
|
|||
val flatten : 'a gen t -> 'a t
|
||||
(** Flatten the enumeration of generators *)
|
||||
|
||||
val flatMap : ('a -> 'b gen) -> 'a t -> 'b t
|
||||
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. *)
|
||||
|
|
@ -127,19 +127,24 @@ module type S = sig
|
|||
(** 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 takeWhile : ('a -> bool) -> 'a t -> 'a t
|
||||
val take_while : ('a -> bool) -> 'a t -> 'a t
|
||||
(** Take elements while they satisfy the predicate *)
|
||||
|
||||
val dropWhile : ('a -> bool) -> 'a t -> 'a t
|
||||
val drop_while : ('a -> bool) -> 'a t -> 'a t
|
||||
(** Drop elements while they satisfy the predicate *)
|
||||
|
||||
val filterMap : ('a -> 'b option) -> 'a t -> 'b t
|
||||
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
|
||||
(** Maps some elements to 'b, drop the other ones *)
|
||||
|
||||
val zipIndex : 'a t -> (int * 'a) t
|
||||
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
|
||||
|
|
@ -199,7 +204,7 @@ module type S = sig
|
|||
(** Succeeds if some pair of elements satisfy the predicate.
|
||||
Ignores elements of an iterator if the other runs dry. *)
|
||||
|
||||
val zipWith : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
||||
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
|
||||
|
|
|
|||
|
|
@ -74,9 +74,6 @@ let rec equal f l1 l2 = match l1, l2 with
|
|||
| [], _ | _, [] -> false
|
||||
| x1::l1', x2::l2' -> f x1 x2 && equal f l1' l2'
|
||||
|
||||
(* difference list *)
|
||||
type 'a dlist = 'a list -> 'a list
|
||||
|
||||
(* append difference lists *)
|
||||
let _d_append f1 f2 =
|
||||
fun l -> f1 (f2 l)
|
||||
|
|
@ -290,7 +287,7 @@ module Idx = struct
|
|||
Idx.insert [1;2;3] 1 10 = [1;10;2;3]
|
||||
*)
|
||||
|
||||
let rec remove l0 i =
|
||||
let remove l0 i =
|
||||
let rec aux l acc i = match l with
|
||||
| [] -> l0
|
||||
| _::l' when i=0 -> List.rev_append acc l'
|
||||
|
|
@ -383,6 +380,7 @@ end
|
|||
type 'a sequence = ('a -> unit) -> unit
|
||||
type 'a gen = unit -> 'a option
|
||||
type 'a printer = Buffer.t -> 'a -> unit
|
||||
type 'a formatter = Format.formatter -> 'a -> unit
|
||||
|
||||
let to_seq l k = List.iter k l
|
||||
let of_seq seq =
|
||||
|
|
@ -425,3 +423,14 @@ let pp ?(start="[") ?(stop="]") ?(sep=", ") pp_item buf l =
|
|||
(*$T
|
||||
CCPrint.to_string (pp CCPrint.int) [1;2;3] = "[1, 2, 3]"
|
||||
*)
|
||||
|
||||
let print ?(start="[") ?(stop="]") ?(sep=", ") pp_item fmt l =
|
||||
let rec print fmt l = match l with
|
||||
| x::((y::xs) as l) ->
|
||||
pp_item fmt x;
|
||||
Format.pp_print_string fmt sep;
|
||||
print fmt l
|
||||
| x::[] -> pp_item fmt x
|
||||
| [] -> ()
|
||||
in
|
||||
Format.fprintf fmt "@[%s%a%s@]" start print l stop
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ end
|
|||
type 'a sequence = ('a -> unit) -> unit
|
||||
type 'a gen = unit -> 'a option
|
||||
type 'a printer = Buffer.t -> 'a -> unit
|
||||
type 'a formatter = Format.formatter -> 'a -> unit
|
||||
|
||||
val to_seq : 'a t -> 'a sequence
|
||||
val of_seq : 'a sequence -> 'a t
|
||||
|
|
@ -183,3 +184,6 @@ val of_gen : 'a gen -> 'a t
|
|||
|
||||
val pp : ?start:string -> ?stop:string -> ?sep:string ->
|
||||
'a printer -> 'a t printer
|
||||
|
||||
val print : ?start:string -> ?stop:string -> ?sep:string ->
|
||||
'a formatter -> 'a t formatter
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ let foldi f init seq =
|
|||
r := f !r !i elt;
|
||||
incr i);
|
||||
!r
|
||||
|
||||
|
||||
(** Map objects of the sequence into other elements, lazily *)
|
||||
let map f seq =
|
||||
let seq_fun' k = seq (fun x -> k (f x)) in
|
||||
|
|
@ -144,97 +144,94 @@ let intersperse elem seq =
|
|||
|
||||
(** Mutable unrolled list to serve as intermediate storage *)
|
||||
module MList = struct
|
||||
type 'a t = {
|
||||
content : 'a array; (* elements of the node *)
|
||||
mutable len : int; (* number of elements in content *)
|
||||
mutable tl : 'a t; (* tail *)
|
||||
} (** A list that contains some elements, and may point to another list *)
|
||||
type 'a node =
|
||||
| Nil
|
||||
| Cons of 'a array * int ref * 'a node ref
|
||||
|
||||
let _empty () : 'a t = Obj.magic 0
|
||||
(** Empty list, for the tl field *)
|
||||
let of_seq seq =
|
||||
let start = ref Nil in
|
||||
let chunk_size = ref 8 in
|
||||
(* fill the list. prev: tail-reference from previous node *)
|
||||
let prev, cur = ref start, ref Nil in
|
||||
seq
|
||||
(fun x -> match !cur with
|
||||
| Nil ->
|
||||
let n = !chunk_size in
|
||||
if n < 4096 then chunk_size := 2 * !chunk_size;
|
||||
cur := Cons (Array.make n x, ref 1, ref Nil)
|
||||
| Cons (a,n,next) ->
|
||||
assert (!n < Array.length a);
|
||||
a.(!n) <- x;
|
||||
incr n;
|
||||
if !n = Array.length a then begin
|
||||
!prev := !cur;
|
||||
prev := next;
|
||||
cur := Nil
|
||||
end
|
||||
);
|
||||
!prev := !cur;
|
||||
!start
|
||||
|
||||
let make n =
|
||||
assert (n > 0);
|
||||
{ content = Array.make n (Obj.magic 0);
|
||||
len = 0;
|
||||
tl = _empty ();
|
||||
}
|
||||
|
||||
let rec is_empty l =
|
||||
l.len = 0 && (l.tl == _empty () || is_empty l.tl)
|
||||
|
||||
let rec iter f l =
|
||||
for i = 0 to l.len - 1 do f l.content.(i); done;
|
||||
if l.tl != _empty () then iter f l.tl
|
||||
let rec iter f l = match l with
|
||||
| Nil -> ()
|
||||
| Cons (a, n, tl) ->
|
||||
for i=0 to !n - 1 do f a.(i) done;
|
||||
iter f !tl
|
||||
|
||||
let iteri f l =
|
||||
let rec iteri i f l =
|
||||
for j = 0 to l.len - 1 do f (i+j) l.content.(j); done;
|
||||
if l.tl != _empty () then iteri (i+l.len) f l.tl
|
||||
let rec iteri i f l = match l with
|
||||
| Nil -> ()
|
||||
| Cons (a, n, tl) ->
|
||||
for j=0 to !n - 1 do f (i+j) a.(j) done;
|
||||
iteri (i+ !n) f !tl
|
||||
in iteri 0 f l
|
||||
|
||||
let rec iter_rev f l =
|
||||
(if l.tl != _empty () then iter_rev f l.tl);
|
||||
for i = l.len - 1 downto 0 do f l.content.(i); done
|
||||
let rec iter_rev f l = match l with
|
||||
| Nil -> ()
|
||||
| Cons (a, n, tl) ->
|
||||
iter_rev f !tl;
|
||||
for i = !n-1 downto 0 do f a.(i) done
|
||||
|
||||
let length l =
|
||||
let rec len acc l =
|
||||
if l.tl == _empty () then acc+l.len else len (acc+l.len) l.tl
|
||||
let rec len acc l = match l with
|
||||
| Nil -> acc
|
||||
| Cons (_, n, tl) -> len (acc+ !n) !tl
|
||||
in len 0 l
|
||||
|
||||
(** Get element by index *)
|
||||
let rec get l i =
|
||||
if i < l.len then l.content.(i)
|
||||
else if i >= l.len && l.tl == _empty () then raise (Invalid_argument "MList.get")
|
||||
else get l.tl (i - l.len)
|
||||
let rec get l i = match l with
|
||||
| Nil -> raise (Invalid_argument "MList.get")
|
||||
| Cons (a, n, _) when i < !n -> a.(i)
|
||||
| Cons (_, n, tl) -> get !tl (i- !n)
|
||||
|
||||
(** Push [x] at the end of the list. It returns the block in which the
|
||||
element is inserted. *)
|
||||
let rec push x l =
|
||||
if l.len = Array.length l.content
|
||||
then begin (* insert in the next block *)
|
||||
(if l.tl == _empty () then
|
||||
let n = Array.length l.content in
|
||||
l.tl <- make (n + n lsr 1));
|
||||
push x l.tl
|
||||
end else begin (* insert in l *)
|
||||
l.content.(l.len) <- x;
|
||||
l.len <- l.len + 1;
|
||||
l
|
||||
end
|
||||
let to_seq l k = iter k l
|
||||
|
||||
(** Reverse list (in place), and returns the new head *)
|
||||
let rev l =
|
||||
let rec rev prev l =
|
||||
(* reverse array *)
|
||||
for i = 0 to (l.len-1) / 2 do
|
||||
let x = l.content.(i) in
|
||||
l.content.(i) <- l.content.(l.len - i - 1);
|
||||
l.content.(l.len - i - 1) <- x;
|
||||
done;
|
||||
(* reverse next block *)
|
||||
let l' = l.tl in
|
||||
l.tl <- prev;
|
||||
if l' == _empty () then l else rev l l'
|
||||
in
|
||||
rev (_empty ()) l
|
||||
let _to_next arg l =
|
||||
let cur = ref l in
|
||||
let i = ref 0 in (* offset in cons *)
|
||||
let rec get_next _ = match !cur with
|
||||
| Nil -> None
|
||||
| Cons (_, n, tl) when !i = !n ->
|
||||
cur := !tl;
|
||||
i := 0;
|
||||
get_next arg
|
||||
| Cons (a, n, _) ->
|
||||
let x = a.(!i) in
|
||||
incr i;
|
||||
Some x
|
||||
in get_next
|
||||
|
||||
(** Build a MList of elements of the Seq. The optional argument indicates
|
||||
the size of the blocks *)
|
||||
let of_seq ?(size=8) seq =
|
||||
(* read sequence into a MList.t *)
|
||||
let start = make size in
|
||||
let l = ref start in
|
||||
seq (fun x -> l := push x !l);
|
||||
start
|
||||
let to_gen l = _to_next () l
|
||||
|
||||
let to_stream l =
|
||||
Stream.from (_to_next 42 l) (* 42=magic cookiiiiiie *)
|
||||
end
|
||||
|
||||
(** Iterate on the sequence, storing elements in a data structure.
|
||||
The resulting sequence can be iterated on as many times as needed. *)
|
||||
let persistent ?(blocksize=64) seq =
|
||||
if blocksize < 2 then failwith "Sequence.persistent: blocksize too small";
|
||||
let l = MList.of_seq ~size:blocksize seq in
|
||||
from_iter (fun k -> MList.iter k l)
|
||||
let persistent seq =
|
||||
let l = MList.of_seq seq in
|
||||
MList.to_seq l
|
||||
|
||||
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. *)
|
||||
let sort ?(cmp=Pervasives.compare) seq =
|
||||
|
|
@ -316,14 +313,19 @@ let scan f acc seq =
|
|||
let acc = ref acc in
|
||||
seq (fun elt -> let acc' = f !acc elt in k acc'; acc := acc'))
|
||||
|
||||
(** Max element of the sequence, using the given comparison
|
||||
function. A default element has to be provided. *)
|
||||
let max ?(lt=fun x y -> x < y) seq m =
|
||||
fold (fun m x -> if lt m x then x else m) m seq
|
||||
let max ?(lt=fun x y -> x < y) seq =
|
||||
let ret = ref None in
|
||||
seq (fun x -> match !ret with
|
||||
| None -> ret := Some x
|
||||
| Some y -> if lt y x then ret := Some x);
|
||||
!ret
|
||||
|
||||
(** Min element of the sequence, using the given comparison function *)
|
||||
let min ?(lt=fun x y -> x < y) seq m =
|
||||
fold (fun m x -> if lt x m then x else m) m seq
|
||||
let min ?(lt=fun x y -> x < y) seq =
|
||||
let ret = ref None in
|
||||
seq (fun x -> match !ret with
|
||||
| None -> ret := Some x
|
||||
| Some y -> if lt x y then ret := Some x);
|
||||
!ret
|
||||
|
||||
exception ExitSequence
|
||||
|
||||
|
|
@ -337,7 +339,7 @@ let take n seq =
|
|||
incr count;
|
||||
k x;
|
||||
if !count = n then raise ExitSequence)
|
||||
with ExitSequence -> ()
|
||||
with ExitSequence -> ()
|
||||
|
||||
(** Drop the [n] first elements of the sequence *)
|
||||
let drop n seq =
|
||||
|
|
@ -470,14 +472,8 @@ let of_stream s =
|
|||
|
||||
(** Convert to a stream. The sequence is made persistent. *)
|
||||
let to_stream seq =
|
||||
let l = ref (MList.of_seq seq) in
|
||||
let i = ref 0 in
|
||||
let rec get_next () =
|
||||
if !l == MList._empty () then None
|
||||
else if (!l).MList.len = !i then (l := (!l).MList.tl; i := 0; get_next ())
|
||||
else let x = (!l).MList.content.(!i) in (incr i; Some x)
|
||||
in
|
||||
Stream.from (fun _ -> get_next ())
|
||||
let l = MList.of_seq seq in
|
||||
MList.to_stream l
|
||||
|
||||
(** Push elements of the sequence on the stack *)
|
||||
let to_stack s seq = iter (fun x -> Stack.push x s) seq
|
||||
|
|
@ -520,7 +516,7 @@ let hashtbl_values h =
|
|||
from_iter (fun k -> Hashtbl.iter (fun a b -> k b) h)
|
||||
|
||||
let of_str s = from_iter (fun k -> String.iter k s)
|
||||
|
||||
|
||||
let to_str seq =
|
||||
let b = Buffer.create 64 in
|
||||
iter (fun c -> Buffer.add_char b c) seq;
|
||||
|
|
@ -541,6 +537,10 @@ let int_range ~start ~stop =
|
|||
fun k ->
|
||||
for i = start to stop do k i done
|
||||
|
||||
let int_range_dec ~start ~stop =
|
||||
fun k ->
|
||||
for i = start downto stop do k i done
|
||||
|
||||
(** Convert the given set to a sequence. The set module must be provided. *)
|
||||
let of_set (type s) (type v) m set =
|
||||
let module S = (val m : Set.S with type t = s and type elt = v) in
|
||||
|
|
@ -554,6 +554,21 @@ let to_set (type s) (type v) m seq =
|
|||
(fun set x -> S.add x set)
|
||||
S.empty seq
|
||||
|
||||
type 'a gen = unit -> 'a option
|
||||
|
||||
let of_gen g =
|
||||
(* consume the generator to build a MList *)
|
||||
let rec iter1 k = match g () with
|
||||
| None -> ()
|
||||
| Some x -> k x; iter1 k
|
||||
in
|
||||
let l = MList.of_seq iter1 in
|
||||
MList.to_seq l
|
||||
|
||||
let to_gen seq =
|
||||
let l = MList.of_seq seq in
|
||||
MList.to_gen l
|
||||
|
||||
(** {2 Functorial conversions between sets and sequences} *)
|
||||
|
||||
module Set = struct
|
||||
|
|
@ -571,7 +586,7 @@ module Set = struct
|
|||
|
||||
include X
|
||||
end
|
||||
|
||||
|
||||
(** Functor to build an extended Set module from an ordered type *)
|
||||
module Make(X : Set.OrderedType) = struct
|
||||
module MySet = Set.Make(X)
|
||||
|
|
@ -630,70 +645,23 @@ let random_array a =
|
|||
|
||||
let random_list l = random_array (Array.of_list l)
|
||||
|
||||
(** {2 Type-classes} *)
|
||||
|
||||
module TypeClass = struct
|
||||
(** {3 Classes} *)
|
||||
type ('a,'b) sequenceable = {
|
||||
to_seq : 'b -> 'a t;
|
||||
of_seq : 'a t -> 'b;
|
||||
}
|
||||
|
||||
type ('a,'b) addable = {
|
||||
empty : 'b;
|
||||
add : 'b -> 'a -> 'b;
|
||||
}
|
||||
|
||||
type 'a monoid = ('a,'a) addable
|
||||
|
||||
type ('a,'b) iterable = {
|
||||
iter : ('a -> unit) -> 'b -> unit;
|
||||
}
|
||||
|
||||
(** {3 Instances} *)
|
||||
|
||||
let (sequenceable : ('a,'a t) sequenceable) = {
|
||||
to_seq = (fun seq -> seq);
|
||||
of_seq = (fun seq -> seq);
|
||||
}
|
||||
|
||||
let (iterable : ('a, 'a t) iterable) = {
|
||||
iter = (fun f seq -> iter f seq);
|
||||
}
|
||||
|
||||
let (monoid : 'a t monoid) = {
|
||||
empty = empty;
|
||||
add = (fun s1 s2 -> append s1 s2);
|
||||
}
|
||||
|
||||
(** {3 Conversions} *)
|
||||
|
||||
let of_iterable iterable x =
|
||||
from_iter (fun k -> iterable.iter k x)
|
||||
|
||||
|
||||
let to_addable addable seq =
|
||||
fold addable.add addable.empty seq
|
||||
end
|
||||
|
||||
(** {2 Infix functions} *)
|
||||
|
||||
module Infix = struct
|
||||
let (--) i j = int_range ~start:i ~stop:j
|
||||
|
||||
let (|>) x f = f x
|
||||
|
||||
let (@@) a b = append a b
|
||||
|
||||
let (>>=) x f = flatMap f x
|
||||
let (--^) i j = int_range_dec ~start:i ~stop:j
|
||||
end
|
||||
|
||||
include Infix
|
||||
|
||||
(** {2 Pretty printing of sequences} *)
|
||||
|
||||
(** Pretty print a sequence of ['a], using the given pretty printer
|
||||
to print each elements. An optional separator string can be provided. *)
|
||||
let pp_seq ?(sep=", ") pp_elt formatter seq =
|
||||
let print ?(start="") ?(stop="") ?(sep=", ") pp_elt formatter seq =
|
||||
let first = ref true in
|
||||
Format.pp_print_string formatter start;
|
||||
iter
|
||||
(fun x ->
|
||||
(if !first then first := false
|
||||
|
|
@ -702,4 +670,22 @@ let pp_seq ?(sep=", ") pp_elt formatter seq =
|
|||
Format.pp_print_cut formatter ();
|
||||
end);
|
||||
pp_elt formatter x)
|
||||
seq
|
||||
seq;
|
||||
Format.pp_print_string formatter stop;
|
||||
()
|
||||
|
||||
let pp ?(start="") ?(stop="") ?(sep=", ") pp_elt buf seq =
|
||||
let first = ref true in
|
||||
Buffer.add_string buf start;
|
||||
iter
|
||||
(fun x ->
|
||||
if !first then first := false else Buffer.add_string buf sep;
|
||||
pp_elt buf x)
|
||||
seq;
|
||||
Buffer.add_string buf stop;
|
||||
()
|
||||
|
||||
let to_string ?start ?stop ?sep pp_elt seq =
|
||||
let buf = Buffer.create 25 in
|
||||
pp ?start ?stop ?sep pp_elt buf seq;
|
||||
Buffer.contents buf
|
||||
|
|
|
|||
|
|
@ -151,15 +151,11 @@ val fmap : ('a -> 'b option) -> 'a t -> 'b t
|
|||
val intersperse : 'a -> 'a t -> 'a t
|
||||
(** Insert the single element between every element of the sequence *)
|
||||
|
||||
val persistent : ?blocksize:int -> 'a t -> 'a t
|
||||
val persistent : 'a t -> 'a t
|
||||
(** Iterate on the sequence, storing elements in a data structure.
|
||||
The resulting sequence can be iterated on as many times as needed.
|
||||
{b Note}: calling persistent on an already persistent sequence
|
||||
will still make a new copy of the sequence!
|
||||
|
||||
@param blocksize the size of chunks in the unrolled list
|
||||
used to store elements. Use bigger values for bigger sequences.
|
||||
Default: 64 *)
|
||||
will still make a new copy of the sequence! *)
|
||||
|
||||
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
||||
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time.
|
||||
|
|
@ -195,12 +191,14 @@ val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
|||
val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t
|
||||
(** Sequence of intermediate results *)
|
||||
|
||||
val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a -> 'a
|
||||
(** Max element of the sequence, using the given comparison
|
||||
function. A default element has to be provided. *)
|
||||
val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
||||
(** Max element of the sequence, using the given comparison function.
|
||||
@return None if the sequence is empty, Some [m] where [m] is the maximal
|
||||
element otherwise *)
|
||||
|
||||
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a -> 'a
|
||||
(** Min element of the sequence, using the given comparison function *)
|
||||
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
||||
(** Min element of the sequence, using the given comparison function.
|
||||
see {!max} for more details. *)
|
||||
|
||||
val take : int -> 'a t -> 'a t
|
||||
(** Take at most [n] elements from the sequence. Works on infinite
|
||||
|
|
@ -243,7 +241,7 @@ val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a, 'b) t2 -> ('c, 'd) t2
|
|||
val to_list : 'a t -> 'a list
|
||||
|
||||
val to_rev_list : 'a t -> 'a list
|
||||
(** Get the list of the reversed sequence (more efficient) *)
|
||||
(** Get the list of the reversed sequence (more efficient than {!to_list}) *)
|
||||
|
||||
val of_list : 'a list -> 'a t
|
||||
|
||||
|
|
@ -315,7 +313,12 @@ val to_buffer : char t -> Buffer.t -> unit
|
|||
(** Copy content of the sequence into the buffer *)
|
||||
|
||||
val int_range : start:int -> stop:int -> int t
|
||||
(** Iterator on integers in [start...stop] by steps 1 *)
|
||||
(** Iterator on integers in [start...stop] by steps 1. Also see
|
||||
{!(--)} for an infix version. *)
|
||||
|
||||
val int_range_dec : start:int -> stop:int -> int t
|
||||
(** Iterator on decreasing integers in [stop...start] by steps -1.
|
||||
See {!(--^)} for an infix version *)
|
||||
|
||||
val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t
|
||||
(** Convert the given set to a sequence. The set module must be provided. *)
|
||||
|
|
@ -323,6 +326,14 @@ val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t
|
|||
val to_set : (module Set.S with type elt = 'a and type t = 'b) -> 'a t -> 'b
|
||||
(** Convert the sequence to a set, given the proper set module *)
|
||||
|
||||
type 'a gen = unit -> 'a option
|
||||
|
||||
val of_gen : 'a gen -> 'a t
|
||||
(** Traverse eagerly the generator and build a sequence from it *)
|
||||
|
||||
val to_gen : 'a t -> 'a gen
|
||||
(** Make the sequence persistent (O(n)) and then iterate on it. Eager. *)
|
||||
|
||||
(** {2 Functorial conversions between sets and sequences} *)
|
||||
|
||||
module Set : sig
|
||||
|
|
@ -375,51 +386,30 @@ val random_list : 'a list -> 'a t
|
|||
(** Infinite sequence of random elements of the list. Basically the
|
||||
same as {!random_array}. *)
|
||||
|
||||
(** {2 Type-classes} *)
|
||||
|
||||
module TypeClass : sig
|
||||
(** {3 Classes} *)
|
||||
type ('a,'b) sequenceable = {
|
||||
to_seq : 'b -> 'a t;
|
||||
of_seq : 'a t -> 'b;
|
||||
}
|
||||
|
||||
type ('a,'b) addable = {
|
||||
empty : 'b;
|
||||
add : 'b -> 'a -> 'b;
|
||||
}
|
||||
|
||||
type 'a monoid = ('a,'a) addable
|
||||
|
||||
type ('a,'b) iterable = {
|
||||
iter : ('a -> unit) -> 'b -> unit;
|
||||
}
|
||||
|
||||
(** {3 Instances} *)
|
||||
|
||||
val sequenceable : ('a,'a t) sequenceable
|
||||
val iterable : ('a,'a t) iterable
|
||||
val monoid : 'a t monoid
|
||||
|
||||
(** {3 Conversions} *)
|
||||
|
||||
val of_iterable : ('a,'b) iterable -> 'b -> 'a t
|
||||
val to_addable : ('a,'b) addable -> 'a t -> 'b
|
||||
end
|
||||
|
||||
(** {2 Infix functions} *)
|
||||
|
||||
module Infix : sig
|
||||
val (--) : int -> int -> int t
|
||||
|
||||
val (|>) : 'a -> ('a -> 'b) -> 'b
|
||||
|
||||
val (@@) : 'a t -> 'a t -> 'a t
|
||||
val (--^) : int -> int -> int t
|
||||
(** [a --^ b] is the range of integers from [b] to [a], both included,
|
||||
in decreasing order (starts from [a]).
|
||||
It will therefore be empty if [a < b]. *)
|
||||
end
|
||||
|
||||
include module type of Infix
|
||||
|
||||
(** {2 Pretty printing of sequences} *)
|
||||
|
||||
val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) ->
|
||||
val print : ?start:string -> ?stop:string -> ?sep:string ->
|
||||
(Format.formatter -> 'a -> unit) ->
|
||||
Format.formatter -> 'a t -> unit
|
||||
(** Pretty print a sequence of ['a], using the given pretty printer
|
||||
to print each elements. An optional separator string can be provided. *)
|
||||
|
||||
val pp : ?start:string -> ?stop:string -> ?sep:string ->
|
||||
(Buffer.t -> 'a -> unit) ->
|
||||
Buffer.t -> 'a t -> unit
|
||||
|
||||
val to_string : ?start:string -> ?stop:string -> ?sep:string ->
|
||||
(Buffer.t -> 'a -> unit) -> 'a t -> string
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@ let create i =
|
|||
vec = Array.create i (Obj.magic None);
|
||||
}
|
||||
|
||||
(** resize the underlying array so that it can contains the
|
||||
given number of elements *)
|
||||
let resize v newcapacity =
|
||||
assert (newcapacity >= v.size);
|
||||
let new_vec = Array.create newcapacity (Obj.magic None) in
|
||||
|
|
@ -46,7 +44,6 @@ let resize v newcapacity =
|
|||
v.vec <- new_vec;
|
||||
()
|
||||
|
||||
(** Be sure that [v] can contain [size] elements, resize it if needed. *)
|
||||
let ensure v size =
|
||||
if v.size < size
|
||||
then
|
||||
|
|
|
|||
|
|
@ -26,100 +26,104 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
(** {1 Growable, mutable vector} *)
|
||||
|
||||
type 'a t
|
||||
(** the type of a vector of 'a *)
|
||||
(** the type of a vector of 'a *)
|
||||
|
||||
type 'a sequence = ('a -> unit) -> unit
|
||||
|
||||
val create : int -> 'a t
|
||||
(** create a vector of given initial capacity *)
|
||||
(** create a vector of given initial capacity *)
|
||||
|
||||
val clear : 'a t -> unit
|
||||
(** clear the content of the vector *)
|
||||
(** clear the content of the vector *)
|
||||
|
||||
val ensure : 'a t -> int -> unit
|
||||
(** Ensure that the vector can contain that much elements, resizing it
|
||||
if required *)
|
||||
|
||||
val is_empty : 'a t -> bool
|
||||
(** is the vector empty? *)
|
||||
(** is the vector empty? *)
|
||||
|
||||
val push : 'a t -> 'a -> unit
|
||||
(** add an element at the end of the vector *)
|
||||
(** add an element at the end of the vector *)
|
||||
|
||||
val append : 'a t -> 'a t -> unit
|
||||
(** [append a b] adds all elements of b to a *)
|
||||
(** [append a b] adds all elements of b to a *)
|
||||
|
||||
val append_array : 'a t -> 'a array -> unit
|
||||
(** same as append, with an array *)
|
||||
(** same as append, with an array *)
|
||||
|
||||
val append_seq : 'a t -> 'a sequence -> unit
|
||||
(** Append content of sequence *)
|
||||
(** Append content of sequence *)
|
||||
|
||||
val pop : 'a t -> 'a
|
||||
(** remove last element, or raise a Failure if empty *)
|
||||
(** remove last element, or raise a Failure if empty *)
|
||||
|
||||
val copy : 'a t -> 'a t
|
||||
(** shallow copy *)
|
||||
(** shallow copy *)
|
||||
|
||||
val shrink : 'a t -> int -> unit
|
||||
(** shrink to the given size (remove elements above this size) *)
|
||||
(** shrink to the given size (remove elements above this size) *)
|
||||
|
||||
val member : ?eq:('a -> 'a -> bool) -> 'a t -> 'a -> bool
|
||||
(** is the element a member of the vector? *)
|
||||
(** is the element a member of the vector? *)
|
||||
|
||||
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> unit
|
||||
(** sort the array in place*)
|
||||
(** sort the array in place*)
|
||||
|
||||
val uniq_sort : ?cmp:('a -> 'a -> int) -> 'a t -> unit
|
||||
(** sort the array and remove duplicates in place*)
|
||||
(** sort the array and remove duplicates in place*)
|
||||
|
||||
val iter : 'a t -> ('a -> unit) -> unit
|
||||
(** iterate on the vector *)
|
||||
(** iterate on the vector *)
|
||||
|
||||
val iteri : 'a t -> (int -> 'a -> unit) -> unit
|
||||
(** iterate on the vector with indexes *)
|
||||
(** iterate on the vector with indexes *)
|
||||
|
||||
val map : 'a t -> ('a -> 'b) -> 'b t
|
||||
(** map elements of the vector *)
|
||||
(** map elements of the vector *)
|
||||
|
||||
val filter : 'a t -> ('a -> bool) -> 'a t
|
||||
(** filter elements from vector *)
|
||||
(** filter elements from vector *)
|
||||
|
||||
val fold : 'a t -> 'b -> ('b -> 'a -> 'b) -> 'b
|
||||
(** fold on elements of the vector *)
|
||||
(** fold on elements of the vector *)
|
||||
|
||||
val exists : 'a t -> ('a -> bool) -> bool
|
||||
(** existential test *)
|
||||
(** existential test *)
|
||||
|
||||
val for_all : 'a t -> ('a -> bool) -> bool
|
||||
(** universal test *)
|
||||
(** universal test *)
|
||||
|
||||
val find : 'a t -> ('a -> bool) -> 'a
|
||||
(** find an element that satisfies the predicate, or Not_found *)
|
||||
(** find an element that satisfies the predicate, or Not_found *)
|
||||
|
||||
val get : 'a t -> int -> 'a
|
||||
(** access element, or Failure if bad index *)
|
||||
(** access element, or Failure if bad index *)
|
||||
|
||||
val set : 'a t -> int -> 'a -> unit
|
||||
(** access element, or Failure if bad index *)
|
||||
(** access element, or Failure if bad index *)
|
||||
|
||||
val rev : 'a t -> unit
|
||||
(** Reverse array in place *)
|
||||
(** Reverse array in place *)
|
||||
|
||||
val size : 'a t -> int
|
||||
(** number of elements in vector *)
|
||||
(** number of elements in vector *)
|
||||
|
||||
val length : _ t -> int
|
||||
(** Synonym for {! size} *)
|
||||
(** Synonym for {! size} *)
|
||||
|
||||
val unsafe_get_array : 'a t -> 'a array
|
||||
(** Access the underlying *shared* array (do not modify!).
|
||||
[unsafe_get_array v] is longer than [size v], but elements at higher
|
||||
index than [size v] are undefined (do not access!). *)
|
||||
(** Access the underlying *shared* array (do not modify!).
|
||||
[unsafe_get_array v] is longer than [size v], but elements at higher
|
||||
index than [size v] are undefined (do not access!). *)
|
||||
|
||||
val of_seq : ?init:'a t -> 'a sequence -> 'a t
|
||||
|
||||
val to_seq : 'a t -> 'a sequence
|
||||
|
||||
val slice : 'a t -> int -> int -> 'a sequence
|
||||
(** [slice v start len] is the sequence of elements from [v.(start)]
|
||||
to [v.(start+len)] included. *)
|
||||
(** [slice v start len] is the sequence of elements from [v.(start)]
|
||||
to [v.(start+len)] included. *)
|
||||
|
||||
val from_array : 'a array -> 'a t
|
||||
val from_list : 'a list -> 'a t
|
||||
|
|
|
|||
|
|
@ -578,13 +578,13 @@ module Dot = struct
|
|||
(function
|
||||
| Full.EnterVertex (v, attrs, _, _) ->
|
||||
Format.fprintf formatter " @[<h>%a [%a];@]@." pp_vertex v
|
||||
(CCSequence.pp_seq ~sep:"," print_attribute) (CCSequence.of_list attrs)
|
||||
(CCList.print ~sep:"," print_attribute) attrs
|
||||
| Full.ExitVertex _ -> ()
|
||||
| Full.MeetEdge (v2, attrs, v1, _) ->
|
||||
Format.fprintf formatter " @[<h>%a -> %a [%a];@]@."
|
||||
pp_vertex v1 pp_vertex v2
|
||||
(CCSequence.pp_seq ~sep:"," print_attribute)
|
||||
(CCSequence.of_list attrs))
|
||||
(CCList.print ~sep:"," print_attribute)
|
||||
attrs)
|
||||
events;
|
||||
(* close *)
|
||||
Format.fprintf formatter "}@]@;@?";
|
||||
|
|
|
|||
|
|
@ -346,15 +346,15 @@ let pp ~name ?vertices
|
|||
let attributes = print_edge v1 e v2 in
|
||||
Format.fprintf formatter " @[<h>%a -> %a [%a];@]@."
|
||||
pp_vertex v1 pp_vertex v2
|
||||
(CCSequence.pp_seq ~sep:"," print_attribute)
|
||||
(CCSequence.of_list attributes))
|
||||
(CCList.print ~sep:"," print_attribute)
|
||||
attributes)
|
||||
(to_seq graph);
|
||||
(* print vertices *)
|
||||
PHashtbl.iter
|
||||
(fun v _ ->
|
||||
let attributes = print_vertex v in
|
||||
Format.fprintf formatter " @[<h>%a [%a];@]@." pp_vertex v
|
||||
(CCSequence.pp_seq ~sep:"," print_attribute) (CCSequence.of_list attributes))
|
||||
(CCList.print ~sep:"," print_attribute) attributes)
|
||||
vertices;
|
||||
(* close *)
|
||||
Format.fprintf formatter "}@]@;";
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ let bench_enum () =
|
|||
let enum () =
|
||||
let open CCGen in
|
||||
let seq = int_range 0 n in
|
||||
let seq = flatMap (fun x -> int_range x (x+10)) seq in
|
||||
let seq = flat_map (fun x -> int_range x (x+10)) seq in
|
||||
fold (+) 0 seq in
|
||||
Bench.bench
|
||||
[ "sequence.flatMap", seq;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue