diff --git a/src/data/CCPersistentArray.ml b/src/data/CCPersistentArray.ml index 4929eed4..4746df78 100644 --- a/src/data/CCPersistentArray.ml +++ b/src/data/CCPersistentArray.ml @@ -74,20 +74,92 @@ let iteri f t = Array.iteri f (reroot t) let fold_left f acc t = Array.fold_left f acc (reroot t) let fold_right f t acc = Array.fold_right f (reroot t) acc +let append a b = + let n = length a in + init (n + length b) + (fun i -> if i < n then get a i else get b (i-n)) + +let flatten a = + let a = reroot a in + let n = Array.fold_left (fun acc x -> acc + length x) 0 a in + let i = ref 0 in (* index in [a] *) + let j = ref 0 in (* index in [a.(!i)] *) + init n + (fun _ -> + while !j = length a.(!i) do + incr i; + j := 0 + done; + let x = get a.(!i) !j in + incr j; + x + ) + +let flat_map f a = + let a' = map f a in + flatten a' + +(*$T + of_list [ of_list [1]; of_list []; of_list [2;3;4]; of_list [5]; of_list [6;7]] \ + |> flatten |> to_list = [1;2;3;4;5;6;7] + of_list [ of_list []; of_list []; of_list []] |> flatten |> length = 0 + of_list [] |> flatten |> length = 0 +*) + let to_array t = Array.copy (reroot t) let of_array a = init (Array.length a) (fun i -> a.(i)) let to_list t = Array.to_list (reroot t) let of_list l = ref (Array (Array.of_list l)) +let rev_in_place_ a i ~len = + if len=0 then () + else + for k = 0 to (len-1)/2 do + let t = a.(i+k) in + a.(i+k) <- a.(i+len-1-k); + a.(i+len-1-k) <- t; + done + +let of_rev_list l = + let a = Array.of_list l in + rev_in_place_ a 0 ~len:(Array.length a); + ref (Array a) + type 'a sequence = ('a -> unit) -> unit +type 'a gen = unit -> 'a option let to_seq a yield = iter yield a let of_seq seq = let l = ref [] in seq (fun x -> l := x :: !l); - of_list (List.rev !l) + of_rev_list !l + +let rec gen_iter_ f g = match g() with + | None -> () + | Some x -> f x ; gen_iter_ f g + +let of_gen g = + let l = ref [] in + gen_iter_ (fun x -> l := x :: !l) g; + of_rev_list !l + +let to_gen a = + let i = ref 0 in + let n = length a in + fun () -> + if !i = n then None + else ( + let x = get a !i in + incr i; + Some x + ) + +(*$Q + Q.(list int) (fun l -> \ + of_list l |> to_gen |> of_gen |> to_list = l) + *) type 'a printer = Format.formatter -> 'a -> unit diff --git a/src/data/CCPersistentArray.mli b/src/data/CCPersistentArray.mli index 57f7fb64..e333e096 100644 --- a/src/data/CCPersistentArray.mli +++ b/src/data/CCPersistentArray.mli @@ -84,6 +84,18 @@ val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b (** Fold on the elements of the array. *) +val append : 'a t -> 'a t -> 'a t +(** Append the two arrays + @since NEXT_RELEASE *) + +val flatten : 'a t t -> 'a t +(** Concatenates all the sub-arrays + @since NEXT_RELEASE *) + +val flat_map : ('a -> 'b t) -> 'a t -> 'b t +(** Flat map (map + concatenation) + @since NEXT_RELEASE *) + val to_array : 'a t -> 'a array (** [to_array t] returns a mutable copy of [t]. *) @@ -96,12 +108,27 @@ val to_list : 'a t -> 'a list val of_list : 'a list -> 'a t (** [of_list l] returns a fresh persistent array containing the elements of [l]. *) +val of_rev_list : 'a list -> 'a t +(** [of_rev_list l] is the same as [of_list (List.rev l)] but more efficient + @since NEXT_RELEASE *) + +(** {2 Conversions} *) + type 'a sequence = ('a -> unit) -> unit +type 'a gen = unit -> 'a option val to_seq : 'a t -> 'a sequence val of_seq : 'a sequence -> 'a t +val of_gen : 'a gen -> 'a t +(** @since NEXT_RELEASE *) + +val to_gen : 'a t -> 'a gen +(** @since NEXT_RELEASE *) + +(** {2 IO} *) + type 'a printer = Format.formatter -> 'a -> unit val print : 'a printer -> 'a t printer