From d204e1946f7c9e3709347f4fd8eb7eb36bb32ab1 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 31 Aug 2015 16:13:28 +0200 Subject: [PATCH] add `CCDeque.{fold,append_{front,back},{of,to}_{gen,list}}` and others --- src/data/CCDeque.ml | 96 ++++++++++++++++++++++++++++++++++++++++++++ src/data/CCDeque.mli | 58 ++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/src/data/CCDeque.ml b/src/data/CCDeque.ml index 33692272..0cd402a4 100644 --- a/src/data/CCDeque.ml +++ b/src/data/CCDeque.ml @@ -113,6 +113,29 @@ let iter f d = in iter first +(*$T + let n = ref 0 in iter (fun _ -> incr n) (of_list [1;2;3]); !n = 3 +*) + +let append_front ~into q = iter (push_front into) q + +let append_back ~into q = iter (push_back into) q + +let fold f acc d = + match !d with + | None -> acc + | Some first -> + let rec aux acc elt = + let acc = f acc elt.content in + if elt.next != first then aux acc elt.next else acc + in + aux acc first + +(*$T + fold (+) 0 (of_list [1;2;3]) = 6 + fold (fun acc x -> x::acc) [] (of_list [1;2;3]) = [3;2;1] +*) + let length (d : _ t) = match !d with | None -> 0 @@ -122,6 +145,19 @@ let length (d : _ t) = !r type 'a sequence = ('a -> unit) -> unit +type 'a gen = unit -> 'a option + +let add_seq_back q seq = seq (fun x -> push_back q x) + +let add_seq_front q seq = seq (fun x -> push_front q x) + +(*$R + let q = of_list [4;5] in + add_seq_front q Sequence.(of_list [3;2;1]); + assert_equal [1;2;3;4;5] (to_list q); + add_seq_back q Sequence.(of_list [6;7]); + assert_equal [1;2;3;4;5;6;7] (to_list q); +*) let of_seq ?(deque=create ()) seq = seq (fun x -> push_back deque x); @@ -129,12 +165,72 @@ let of_seq ?(deque=create ()) seq = let to_seq d k = iter k d +let of_list l = + let q = create() in + List.iter (push_back q) l; + q + +let to_rev_list q = fold (fun l x -> x::l) [] q + +let to_list q = List.rev (to_rev_list q) + +let gen_empty_ () = None +let rec gen_iter_ f g = match g() with + | None -> () + | Some x -> f x; gen_iter_ f g + +let of_gen g = + let q = create () in + gen_iter_ (fun x -> push_back q x) g; + q + +let to_gen q = match !q with + | None -> gen_empty_ + | Some q -> + let cur = ref q in + let first = ref true in + fun () -> + let x = (!cur).content in + if !cur == q && not !first then None + else ( + first := false; + cur := (!cur).next; + Some x + ) + +(*$T + of_list [1;2;3] |> to_gen |> of_gen |> to_list = [1;2;3] +*) + +(*$Q + Q.(list int) (fun l -> \ + of_list l |> to_gen |> of_gen |> to_list = l) +*) + (* naive implem of copy, for now *) let copy d = let d' = create () in iter (fun x -> push_back d' x) d; d' +let equal ?(eq=(=)) a b = + let rec aux eq a b = match a() , b() with + | None, None -> true + | None, Some _ + | Some _, None -> false + | Some x, Some y -> eq x y && aux eq a b + in aux eq (to_gen a) (to_gen b) + +let compare ?(cmp=Pervasives.compare) a b = + let rec aux cmp a b = match a() , b() with + | None, None -> 0 + | None, Some _ -> -1 + | Some _, None -> 1 + | Some x, Some y -> + let c = cmp x y in + if c=0 then aux cmp a b else c + in aux cmp (to_gen a) (to_gen b) + type 'a printer = Format.formatter -> 'a -> unit let print pp_x out d = diff --git a/src/data/CCDeque.mli b/src/data/CCDeque.mli index 1f41f2cf..1c702d86 100644 --- a/src/data/CCDeque.mli +++ b/src/data/CCDeque.mli @@ -36,6 +36,17 @@ val create : unit -> 'a t val is_empty : 'a t -> bool (** Is the deque empty? *) +val equal : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> bool +(** [equal a b] checks whether [a] and [b] contain the same sequence of + elements. + @param eq comparison function for elements + @since NEXT_RELEASE *) + +val compare : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t -> int +(** [equal a b] compares lexicographically [a] and [b] + @param cmp comparison function for elements + @since NEXT_RELEASE *) + val length : 'a t -> int (** Number of elements (linear) *) @@ -57,18 +68,65 @@ val take_back : 'a t -> 'a val take_front : 'a t -> 'a (** Take first value, or raise Empty *) +val append_front : into:'a t -> 'a t -> unit +(** [append_front ~into q] adds all elements of [q] at the front + of [into] + @since NEXT_RELEASE *) + +val append_back : into:'a t -> 'a t -> unit +(** [append_back ~into q] adds all elements of [q] at the back of [into] + @since NEXT_RELEASE *) + val iter : ('a -> unit) -> 'a t -> unit (** Iterate on elements *) +val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b +(** Fold on elements + @since NEXT_RELEASE *) + +(** {2 Conversions} *) + +type 'a gen = unit -> 'a option type 'a sequence = ('a -> unit) -> unit val of_seq : ?deque:'a t -> 'a sequence -> 'a t val to_seq : 'a t -> 'a sequence +val of_gen : 'a gen -> 'a t +(** [of_gen g] makes a deque containing the elements of [g] + @since NEXT_RELEASE *) + +val to_gen : 'a t -> 'a gen +(** Iterates on elements of the deque + @since NEXT_RELEASE *) + +val add_seq_front : 'a t -> 'a sequence -> unit +(** [add_seq_front q seq] adds elements of [seq] into the front of [q], + in reverse order + @since NEXT_RELEASE *) + +val add_seq_back : 'a t -> 'a sequence -> unit +(** [add_seq_back q seq] adds elements of [seq] into the back of [q], + in order + @since NEXT_RELEASE *) + val copy : 'a t -> 'a t (** Fresh copy *) +val of_list : 'a list -> 'a t +(** Conversion from list, in order + @since NEXT_RELEASE *) + +val to_list : 'a t -> 'a list +(** List of elements, in order + {b warning: not tailrec} + @since NEXT_RELEASE *) + +val to_rev_list : 'a t -> 'a list +(** Efficient conversion to list, in reverse order + @since NEXT_RELEASE *) + type 'a printer = Format.formatter -> 'a -> unit val print : 'a printer -> 'a t printer