From 113ea6d395289c8b5ad8d4f443836125e8ccbb8d Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sat, 17 May 2014 01:00:00 +0200 Subject: [PATCH] updated and fixed things in core/: fixed warnings, updated Sequence/Gen with tests and more recent interface; added printers --- core/CCGen.ml | 466 ++++++++++++++++++++++++++++++++-------- core/CCGen.mli | 17 +- core/CCList.ml | 17 +- core/CCList.mli | 4 + core/CCSequence.ml | 276 +++++++++++------------- core/CCSequence.mli | 88 ++++---- core/CCVector.ml | 3 - core/CCVector.mli | 68 +++--- misc/lazyGraph.ml | 6 +- misc/persistentGraph.ml | 6 +- tests/benchs.ml | 2 +- 11 files changed, 613 insertions(+), 340 deletions(-) diff --git a/core/CCGen.ml b/core/CCGen.ml index fa5e5378..a2db99d7 100644 --- a/core/CCGen.ml +++ b/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] +*) diff --git a/core/CCGen.mli b/core/CCGen.mli index 18ddf1ec..c61670f6 100644 --- a/core/CCGen.mli +++ b/core/CCGen.mli @@ -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 diff --git a/core/CCList.ml b/core/CCList.ml index 14325802..cad0c945 100644 --- a/core/CCList.ml +++ b/core/CCList.ml @@ -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 diff --git a/core/CCList.mli b/core/CCList.mli index ecfa2388..0d84aac2 100644 --- a/core/CCList.mli +++ b/core/CCList.mli @@ -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 diff --git a/core/CCSequence.ml b/core/CCSequence.ml index e5ddf09d..b2e15ded 100644 --- a/core/CCSequence.ml +++ b/core/CCSequence.ml @@ -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 diff --git a/core/CCSequence.mli b/core/CCSequence.mli index 86b6ba34..9ac6c616 100644 --- a/core/CCSequence.mli +++ b/core/CCSequence.mli @@ -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 diff --git a/core/CCVector.ml b/core/CCVector.ml index 283f293a..0ea564e7 100644 --- a/core/CCVector.ml +++ b/core/CCVector.ml @@ -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 diff --git a/core/CCVector.mli b/core/CCVector.mli index 6e973da7..697c601e 100644 --- a/core/CCVector.mli +++ b/core/CCVector.mli @@ -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 diff --git a/misc/lazyGraph.ml b/misc/lazyGraph.ml index 02201ad4..82a664d8 100644 --- a/misc/lazyGraph.ml +++ b/misc/lazyGraph.ml @@ -578,13 +578,13 @@ module Dot = struct (function | Full.EnterVertex (v, attrs, _, _) -> Format.fprintf formatter " @[%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 " @[%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 "}@]@;@?"; diff --git a/misc/persistentGraph.ml b/misc/persistentGraph.ml index cd23cab1..1928e6f5 100644 --- a/misc/persistentGraph.ml +++ b/misc/persistentGraph.ml @@ -346,15 +346,15 @@ let pp ~name ?vertices let attributes = print_edge v1 e v2 in Format.fprintf formatter " @[%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 " @[%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 "}@]@;"; diff --git a/tests/benchs.ml b/tests/benchs.ml index 51f96ccf..bce6dd0c 100644 --- a/tests/benchs.ml +++ b/tests/benchs.ml @@ -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;