From 80e9057a0005b05772cf2370c5f0f84f3faac76a Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 11 Aug 2015 19:09:59 +0200 Subject: [PATCH 01/10] iterate on booleans --- sequence.ml | 2 ++ sequence.mli | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/sequence.ml b/sequence.ml index 2fefe5f..76572a0 100644 --- a/sequence.ml +++ b/sequence.ml @@ -578,6 +578,8 @@ let int_range ~start ~stop k = let int_range_dec ~start ~stop k = for i = start downto stop do k i done +let bools k = k false; k true + 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 fun k -> S.iter k set diff --git a/sequence.mli b/sequence.mli index 7c84c6a..5f73abf 100644 --- a/sequence.mli +++ b/sequence.mli @@ -422,6 +422,10 @@ 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 bools : bool t + (** Iterates on [true] and [false] + @since NEXT_RELEASE *) + 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. *) From d6b7131fd87ac1eab730ae01fbddb5c635537dda Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sat, 22 Aug 2015 23:49:17 +0200 Subject: [PATCH 02/10] alias `group_succ_by`, deprecated `group` --- sequence.ml | 4 +++- sequence.mli | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/sequence.ml b/sequence.ml index 76572a0..1401c8d 100644 --- a/sequence.ml +++ b/sequence.ml @@ -238,7 +238,7 @@ let sort ?(cmp=Pervasives.compare) seq = let l = List.fast_sort cmp l in fun k -> List.iter k l -let group ?(eq=fun x y -> x = y) seq k = +let group_succ_by ?(eq=fun x y -> x = y) seq k = let cur = ref [] in seq (fun x -> match !cur with @@ -251,6 +251,8 @@ let group ?(eq=fun x y -> x = y) seq k = (* last list *) if !cur <> [] then k !cur +let group = group_succ_by + let uniq ?(eq=fun x y -> x = y) seq k = let has_prev = ref false and prev = ref (Obj.magic 0) in (* avoid option type, costly *) diff --git a/sequence.mli b/sequence.mli index 5f73abf..4104b02 100644 --- a/sequence.mli +++ b/sequence.mli @@ -215,7 +215,14 @@ val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t (** Sort the sequence and remove duplicates. Eager, same as [sort] *) val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t - (** Group equal consecutive elements. *) + (** Group equal consecutive elements. + @deprecated use {!group_succ_by} *) + +val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t + (** Group equal consecutive elements. + Synonym to {!group}. + @since NEXT_RELEASE *) + val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t (** Remove consecutive duplicate elements. Basically this is From 8c06c13563ba27b64c9cf79db9d6875bef253a2e Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sat, 22 Aug 2015 23:49:36 +0200 Subject: [PATCH 03/10] add `group_by` (ignores the ordering) --- sequence.ml | 16 ++++++++++++++++ sequence.mli | 5 +++++ tests/test_sequence.ml | 12 +++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/sequence.ml b/sequence.ml index 1401c8d..c781d53 100644 --- a/sequence.ml +++ b/sequence.ml @@ -253,6 +253,22 @@ let group_succ_by ?(eq=fun x y -> x = y) seq k = let group = group_succ_by +let group_by (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq = + let module Tbl = Hashtbl.Make(struct + type t = k + let equal = eq + let hash = hash + end) in + (* compute group table *) + let tbl = Tbl.create 32 in + seq + (fun x -> + let l = try Tbl.find tbl x with Not_found -> [] in + Tbl.replace tbl x (x::l) + ); + fun yield -> + Tbl.iter (fun _ l -> yield l) tbl + let uniq ?(eq=fun x y -> x = y) seq k = let has_prev = ref false and prev = ref (Obj.magic 0) in (* avoid option type, costly *) diff --git a/sequence.mli b/sequence.mli index 4104b02..56969c5 100644 --- a/sequence.mli +++ b/sequence.mli @@ -223,6 +223,11 @@ val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t Synonym to {!group}. @since NEXT_RELEASE *) +val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> + 'a t -> 'a list t + (** Group equal elements, disregarding their order of appearance. + The result sequence is traversable as many times as required. + @since NEXT_RELEASE *) val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t (** Remove consecutive duplicate elements. Basically this is diff --git a/tests/test_sequence.ml b/tests/test_sequence.ml index 8fd1b17..a85a5c6 100644 --- a/tests/test_sequence.ml +++ b/tests/test_sequence.ml @@ -124,11 +124,16 @@ let test_sort_uniq () = |> S.to_list |> OUnit.assert_equal [1;2;3;4;5;42] -let test_group () = +let test_group_succ () = [1;2;3;3;2;2;3;4] - |> S.of_list |> S.group ?eq:None |> S.to_list + |> S.of_list |> S.group_succ_by ?eq:None |> S.to_list |> OUnit.assert_equal [[1];[2];[3;3];[2;2];[3];[4]] +let test_group_by () = + [1;2;3;3;2;2;3;4] + |> S.of_list |> S.group_by ?eq:None ?hash:None |> S.sort ?cmp:None |> S.to_list + |> OUnit.assert_equal [[1];[2;2;2];[3;3;3];[4]] + let test_uniq () = [1;2;2;3;4;4;4;3;3] |> S.of_list |> S.uniq ?eq:None |> S.to_list @@ -226,7 +231,8 @@ let suite = "test_big_persistent" >:: test_big_persistent; "test_sort" >:: test_sort; "test_sort_uniq" >:: test_sort; - "test_group" >:: test_group; + "test_group_succ_by" >:: test_group_succ; + "test_group_by" >:: test_group_by; "test_uniq" >:: test_uniq; "test_product" >:: test_product; "test_join" >:: test_join; From d35c25e783d2dc7e1e6179d9252b44472dca7955 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 25 Aug 2015 09:42:42 +0200 Subject: [PATCH 04/10] some tests were not run --- tests/test_sequence.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_sequence.ml b/tests/test_sequence.ml index a85a5c6..dd301e4 100644 --- a/tests/test_sequence.ml +++ b/tests/test_sequence.ml @@ -243,5 +243,7 @@ let suite = "test_hashtbl" >:: test_hashtbl; "test_int_range" >:: test_int_range; "test_take" >:: test_take; + "test_fold_while" >:: test_fold_while; + "test_buff" >:: test_buff; "test_regression1" >:: test_regression1; ] From 5a3c20464d246e3d7a7e58418494364928ba728f Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sat, 29 Aug 2015 20:22:33 +0200 Subject: [PATCH 05/10] fix test --- tests/test_sequence.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_sequence.ml b/tests/test_sequence.ml index dd301e4..36ed407 100644 --- a/tests/test_sequence.ml +++ b/tests/test_sequence.ml @@ -230,7 +230,7 @@ let suite = "test_persistent" >:: test_persistent; "test_big_persistent" >:: test_big_persistent; "test_sort" >:: test_sort; - "test_sort_uniq" >:: test_sort; + "test_sort_uniq" >:: test_sort_uniq; "test_group_succ_by" >:: test_group_succ; "test_group_by" >:: test_group_by; "test_uniq" >:: test_uniq; From 35c32b1a3221a33bea096d5516c1096b1e7320d2 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 2 Sep 2015 13:59:52 +0200 Subject: [PATCH 06/10] add a test --- tests/test_sequence.ml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_sequence.ml b/tests/test_sequence.ml index 36ed407..de1460b 100644 --- a/tests/test_sequence.ml +++ b/tests/test_sequence.ml @@ -208,6 +208,19 @@ let test_take () = OUnit.assert_equal ~printer:pp_ilist [1;2;3;4;5] l; () +let test_for_all () = + OUnit.assert_bool "true" S.(for_all (fun x -> x < 10) (1--9)); + OUnit.assert_bool "false" S.(not (for_all (fun x -> x < 10) (2--11))); + OUnit.assert_bool "true" S.(for_all (fun _ -> false) empty); + OUnit.assert_bool "nested" + S.( + for_all + (fun seq -> + not (for_all (fun x -> x < 8) seq) + ) (1 -- 10 >|= fun x -> x--20) + ); + () + let test_regression1 () = let s = S.(take 10 (repeat 1)) in OUnit.assert_bool "not empty" (not (S.is_empty s)); @@ -245,5 +258,6 @@ let suite = "test_take" >:: test_take; "test_fold_while" >:: test_fold_while; "test_buff" >:: test_buff; + "test_for_all" >:: test_for_all; "test_regression1" >:: test_regression1; ] From 9d157fe392b028048f26ebfd3d9e751e8f30b328 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 1 Dec 2015 21:59:08 +0100 Subject: [PATCH 07/10] opam: depend on ocamlbuild --- opam | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/opam b/opam index 98868b5..15aba0c 100644 --- a/opam +++ b/opam @@ -12,7 +12,11 @@ install: [make "install"] remove: [ ["ocamlfind" "remove" "sequence"] ] -depends: ["ocamlfind" "base-bytes"] +depends: [ + "ocamlfind" + "base-bytes" + "ocamlbuild" {build} +] tags: [ "sequence" "iterator" "iter" "fold" ] homepage: "https://github.com/c-cube/sequence/" depopts: ["delimcc" "base-bigarray"] From ae1932fba4912202ca520ddb0e32e91fe63aa9b7 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 8 Jan 2016 20:32:58 +0100 Subject: [PATCH 08/10] deprecate `flatMap` and `fmap` --- sequence.mli | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sequence.mli b/sequence.mli index 56969c5..26d0f6b 100644 --- a/sequence.mli +++ b/sequence.mli @@ -168,18 +168,18 @@ val flatten : 'a t t -> 'a t (** Alias for {!concat} *) val flatMap : ('a -> 'b t) -> 'a t -> 'b t - (** Monadic bind. Intuitively, it applies the function to every element of the - initial sequence, and calls {!concat}. *) + (** @deprecated use {!flat_map} since NEXT_RELEASE *) val flat_map : ('a -> 'b t) -> 'a t -> 'b t - (** Alias to {!flatMap} with a more explicit name + (** Monadic bind. Intuitively, it applies the function to every element of the + initial sequence, and calls {!concat}. @since 0.5 *) val fmap : ('a -> 'b option) -> 'a t -> 'b t - (** Specialized version of {!flatMap} for options. *) + (** @deprecated use {!filter_map} since NEXT_RELEASE *) val filter_map : ('a -> 'b option) -> 'a t -> 'b t - (** Alias to {!fmap} with a more explicit name + (** Map and only keep non-[None] elements @since 0.5 *) val intersperse : 'a -> 'a t -> 'a t From 117755aa33afd5df9a5d5e2395d6314668fb1f4b Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 8 Jan 2016 20:41:18 +0100 Subject: [PATCH 09/10] style and license headers --- LICENSE | 2 +- sequence.ml | 251 +++++++++++-------------- sequence.mli | 454 +++++++++++++++++++++------------------------ sequenceLabels.mli | 406 +++++++++++++++++++--------------------- 4 files changed, 519 insertions(+), 594 deletions(-) diff --git a/LICENSE b/LICENSE index 7e29992..28fdb73 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012, Simon Cruanes +Copyright (c) 2012-2016, Simon Cruanes All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/sequence.ml b/sequence.ml index c781d53..c118fb9 100644 --- a/sequence.ml +++ b/sequence.ml @@ -1,29 +1,7 @@ -(* -Copyright (c) 2013, Simon Cruanes -All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +(* This file is free software, part of sequence. See file "license" for more details. *) -Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. Redistributions in binary -form must reproduce the above copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other materials provided with -the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*) - -(** {1 Transient iterators, that abstract on a finite sequence of elements.} *) +(** {1 Simple and Efficient Iterators} *) (** Sequence abstract iterator type *) type 'a t = ('a -> unit) -> unit @@ -31,7 +9,7 @@ type 'a t = ('a -> unit) -> unit type 'a sequence = 'a t type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit - (** Sequence of pairs of values of type ['a] and ['b]. *) +(** Sequence of pairs of values of type ['a] and ['b]. *) (** Build a sequence from a iter function *) let from_iter f = f @@ -69,8 +47,8 @@ let iteri f seq = let r = ref 0 in seq (fun x -> - f !r x; - incr r) + f !r x; + incr r) let fold f init seq = let r = ref init in @@ -82,8 +60,8 @@ let foldi f init seq = let r = ref init in seq (fun elt -> - r := f !r !i elt; - incr i); + r := f !r !i elt; + incr i); !r let map f seq k = seq (fun x -> k (f x)) @@ -108,7 +86,7 @@ let fmap f seq k = seq (fun x -> match f x with | None -> () | Some y -> k y - ) + ) let filter_map = fmap @@ -130,22 +108,20 @@ module MList = struct let prev, cur = ref start, ref Nil in seq (fun x -> - k x; (* callback *) - 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 - ); + k x; (* callback *) + 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 ( + !prev := !cur; + prev := next; + cur := Nil)); !prev := !cur; !start @@ -155,13 +131,13 @@ module MList = struct 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 + for i=0 to !n - 1 do f a.(i) done; + iter f !tl let iteri f l = let rec iteri i f l = match l with - | Nil -> () - | Cons (a, n, tl) -> + | 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 @@ -169,8 +145,8 @@ module MList = struct 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 + iter_rev f !tl; + for i = !n-1 downto 0 do f a.(i) done let length l = let rec len acc l = match l with @@ -192,13 +168,13 @@ module MList = struct let rec get_next _ = match !cur with | Nil -> None | Cons (_, n, tl) when !i = !n -> - cur := !tl; - i := 0; - get_next arg + cur := !tl; + i := 0; + get_next arg | Cons (a, _, _) -> - let x = a.(!i) in - incr i; - Some x + let x = a.(!i) in + incr i; + Some x in get_next let to_gen l = _to_next () l @@ -228,9 +204,9 @@ let persistent_lazy (seq:'a t) = match !r with | LazyCached seq' -> seq' k | LazySuspend -> - (* here if this traversal is interruted, no caching occurs *) - let seq' = MList.of_seq_with seq k in - r := LazyCached (MList.to_seq seq') + (* here if this traversal is interruted, no caching occurs *) + let seq' = MList.of_seq_with seq k in + r := LazyCached (MList.to_seq seq') let sort ?(cmp=Pervasives.compare) seq = (* use an intermediate list, then sort the list *) @@ -241,13 +217,13 @@ let sort ?(cmp=Pervasives.compare) seq = let group_succ_by ?(eq=fun x y -> x = y) seq k = let cur = ref [] in seq (fun x -> - match !cur with - | [] -> cur := [x] - | (y::_) as l when eq x y -> - cur := x::l (* [x] belongs to the group *) - | (_::_) as l -> - k l; (* yield group, and start another one *) - cur := [x]); + match !cur with + | [] -> cur := [x] + | (y::_) as l when eq x y -> + cur := x::l (* [x] belongs to the group *) + | (_::_) as l -> + k l; (* yield group, and start another one *) + cur := [x]); (* last list *) if !cur <> [] then k !cur @@ -255,16 +231,16 @@ let group = group_succ_by let group_by (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq = let module Tbl = Hashtbl.Make(struct - type t = k - let equal = eq - let hash = hash - end) in + type t = k + let equal = eq + let hash = hash + end) in (* compute group table *) let tbl = Tbl.create 32 in seq (fun x -> - let l = try Tbl.find tbl x with Not_found -> [] in - Tbl.replace tbl x (x::l) + let l = try Tbl.find tbl x with Not_found -> [] in + Tbl.replace tbl x (x::l) ); fun yield -> Tbl.iter (fun _ l -> yield l) tbl @@ -272,47 +248,42 @@ let group_by (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq = let uniq ?(eq=fun x y -> x = y) seq k = let has_prev = ref false and prev = ref (Obj.magic 0) in (* avoid option type, costly *) - seq (fun x -> - if !has_prev && eq !prev x + seq + (fun x -> + if !has_prev && eq !prev x then () (* duplicate *) - else begin + else ( has_prev := true; prev := x; k x - end) + )) let sort_uniq (type elt) ?(cmp=Pervasives.compare) seq = let module S = Set.Make(struct - type t = elt - let compare = cmp - end) in + type t = elt + let compare = cmp + end) in let set = fold (fun acc x -> S.add x acc) S.empty seq in fun k -> S.iter k set let product outer inner k = - outer (fun x -> - inner (fun y -> k (x,y)) - ) + outer (fun x -> inner (fun y -> k (x,y))) let product2 outer inner k = - outer (fun x -> - inner (fun y -> k x y) - ) + outer (fun x -> inner (fun y -> k x y)) let join ~join_row s1 s2 k = s1 (fun a -> - s2 (fun b -> - match join_row a b with - | None -> () - | Some c -> k c - ) - ) (* yield the combination of [a] and [b] *) + s2 (fun b -> + match join_row a b with + | None -> () + | Some c -> k c)) let rec unfoldr f b k = match f b with | None -> () | Some (x, b') -> - k x; - unfoldr f b' k + k x; + unfoldr f b' k let scan f acc seq k = k acc; @@ -321,16 +292,18 @@ let scan f acc seq k = 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); + seq + (fun x -> match !ret with + | None -> ret := Some x + | Some y -> if lt y x then ret := Some x); !ret 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); + seq + (fun x -> match !ret with + | None -> ret := Some x + | Some y -> if lt x y then ret := Some x); !ret exception ExitHead @@ -351,11 +324,11 @@ exception ExitTake let take n seq k = let count = ref 0 in try - seq (fun x -> - if !count = n then raise ExitTake; - incr count; - k x; - ) + seq + (fun x -> + if !count = n then raise ExitTake; + incr count; + k x) with ExitTake -> () exception ExitTakeWhile @@ -370,11 +343,11 @@ exception ExitFoldWhile let fold_while f s seq = let state = ref s in let consume x = - let acc, cont = f (!state) x in - state := acc; - match cont with - | `Stop -> raise ExitFoldWhile - | `Continue -> () + let acc, cont = f (!state) x in + state := acc; + match cont with + | `Stop -> raise ExitFoldWhile + | `Continue -> () in try seq consume; !state @@ -386,10 +359,11 @@ let drop n seq k = let drop_while p seq k = let drop = ref true in - seq (fun x -> - if !drop - then if p x then () else (drop := false; k x) - else k x) + seq + (fun x -> + if !drop + then if p x then () else (drop := false; k x) + else k x) let rev seq = let l = MList.of_seq seq in @@ -418,12 +392,13 @@ exception ExitFind let find f seq = let r = ref None in - begin try - seq (fun x -> match f x with - | None -> () - | Some _ as res -> r := res; raise ExitFind - ); - with ExitFind -> () + begin + try + seq + (fun x -> match f x with + | None -> () + | Some _ as res -> r := res; raise ExitFind); + with ExitFind -> () end; !r @@ -492,17 +467,14 @@ let to_array seq = let l = MList.of_seq seq in let n = MList.length l in if n = 0 - then [||] - else begin - let a = Array.make n (MList.get l 0) in - MList.iteri (fun i x -> a.(i) <- x) l; - a - end + then [||] + else ( + let a = Array.make n (MList.get l 0) in + MList.iteri (fun i x -> a.(i) <- x) l; + a + ) -let of_array a k = - for i = 0 to Array.length a - 1 do - k (Array.unsafe_get a i) - done +let of_array a k = Array.iter k a let of_array_i a k = for i = 0 to Array.length a - 1 do @@ -583,8 +555,7 @@ let of_in_channel ic = while true do let c = input_char ic in k c done - with End_of_file -> () - ) + with End_of_file -> ()) let to_buffer seq buf = seq (fun c -> Buffer.add_char buf c) @@ -744,19 +715,19 @@ let pp_seq ?(sep=", ") pp_elt formatter seq = let first = ref true in seq (fun x -> - (if !first then first := false - else begin + (if !first then first := false + else ( Format.pp_print_string formatter sep; Format.pp_print_cut formatter (); - end); - pp_elt formatter x) + )); + pp_elt formatter x) let pp_buf ?(sep=", ") pp_elt buf seq = let first = ref true in seq (fun x -> - if !first then first := false else Buffer.add_string buf sep; - pp_elt buf x) + if !first then first := false else Buffer.add_string buf sep; + pp_elt buf x) let to_string ?sep pp_elt seq = let buf = Buffer.create 25 in @@ -794,7 +765,7 @@ module IO = struct if n' = 0 then stop := true else n := !n + n'; done; if !n > 0 - then k (Bytes.sub_string buf 0 !n) + then k (Bytes.sub_string buf 0 !n) done; close_in ic with e -> diff --git a/sequence.mli b/sequence.mli index 26d0f6b..593f477 100644 --- a/sequence.mli +++ b/sequence.mli @@ -1,27 +1,5 @@ -(* -copyright (c) 2013, simon cruanes -all rights reserved. -redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. redistributions in binary -form must reproduce the above copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other materials provided with -the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*) +(* This file is free software, part of sequence. See file "license" for more details. *) (** {1 Simple and Efficient Iterators} *) @@ -53,252 +31,252 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. of this memory structure, cheaply and repeatably. *) type +'a t = ('a -> unit) -> unit - (** A sequence of values of type ['a]. If you give it a function ['a -> unit] - it will be applied to every element of the sequence successively. *) +(** A sequence of values of type ['a]. If you give it a function ['a -> unit] + it will be applied to every element of the sequence successively. *) type +'a sequence = 'a t type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit - (** Sequence of pairs of values of type ['a] and ['b]. *) +(** Sequence of pairs of values of type ['a] and ['b]. *) (** {2 Build a sequence} *) val from_iter : (('a -> unit) -> unit) -> 'a t - (** Build a sequence from a iter function *) +(** Build a sequence from a iter function *) val from_fun : (unit -> 'a option) -> 'a t - (** Call the function repeatedly until it returns None. This - sequence is transient, use {!persistent} if needed! *) +(** Call the function repeatedly until it returns None. This + sequence is transient, use {!persistent} if needed! *) val empty : 'a t - (** Empty sequence. It contains no element. *) +(** Empty sequence. It contains no element. *) val singleton : 'a -> 'a t - (** Singleton sequence, with exactly one element. *) +(** Singleton sequence, with exactly one element. *) val doubleton : 'a -> 'a -> 'a t - (** Sequence with exactly two elements *) +(** Sequence with exactly two elements *) val cons : 'a -> 'a t -> 'a t - (** [cons x l] yields [x], then yields from [l]. - Same as [append (singleton x) l] *) +(** [cons x l] yields [x], then yields from [l]. + Same as [append (singleton x) l] *) val snoc : 'a t -> 'a -> 'a t - (** Same as {!cons} but yields the element after iterating on [l] *) +(** Same as {!cons} but yields the element after iterating on [l] *) val return : 'a -> 'a t - (** Synonym to {!singleton} *) +(** Synonym to {!singleton} *) val pure : 'a -> 'a t - (** Synonym to {!singleton} *) +(** Synonym to {!singleton} *) val repeat : 'a -> 'a t - (** Infinite sequence of the same element. You may want to look - at {!take} and the likes if you iterate on it. *) +(** Infinite sequence of the same element. You may want to look + at {!take} and the likes if you iterate on it. *) val iterate : ('a -> 'a) -> 'a -> 'a t - (** [iterate f x] is the infinite sequence [x, f(x), f(f(x)), ...] *) +(** [iterate f x] is the infinite sequence [x, f(x), f(f(x)), ...] *) val forever : (unit -> 'b) -> 'b t - (** Sequence that calls the given function to produce elements. - The sequence may be transient (depending on the function), and definitely - is infinite. You may want to use {!take} and {!persistent}. *) +(** Sequence that calls the given function to produce elements. + The sequence may be transient (depending on the function), and definitely + is infinite. You may want to use {!take} and {!persistent}. *) val cycle : 'a t -> 'a t - (** Cycle forever through the given sequence. Assume the given sequence can - be traversed any amount of times (not transient). This yields an - infinite sequence, you should use something like {!take} not to loop - forever. *) +(** Cycle forever through the given sequence. Assume the given sequence can + be traversed any amount of times (not transient). This yields an + infinite sequence, you should use something like {!take} not to loop + forever. *) (** {2 Consume a sequence} *) val iter : ('a -> unit) -> 'a t -> unit - (** Consume the sequence, passing all its arguments to the function. - Basically [iter f seq] is just [seq f]. *) +(** Consume the sequence, passing all its arguments to the function. + Basically [iter f seq] is just [seq f]. *) val iteri : (int -> 'a -> unit) -> 'a t -> unit - (** Iterate on elements and their index in the sequence *) +(** Iterate on elements and their index in the sequence *) val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a - (** Fold over elements of the sequence, consuming it *) +(** Fold over elements of the sequence, consuming it *) val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a - (** Fold over elements of the sequence and their index, consuming it *) +(** Fold over elements of the sequence and their index, consuming it *) val map : ('a -> 'b) -> 'a t -> 'b t - (** Map objects of the sequence into other elements, lazily *) +(** Map objects of the sequence into other elements, lazily *) val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t - (** Map objects, along with their index in the sequence *) +(** Map objects, along with their index in the sequence *) val for_all : ('a -> bool) -> 'a t -> bool - (** Do all elements satisfy the predicate? *) +(** Do all elements satisfy the predicate? *) val exists : ('a -> bool) -> 'a t -> bool - (** Exists there some element satisfying the predicate? *) +(** Exists there some element satisfying the predicate? *) val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool - (** Is the value a member of the sequence? - @param eq the equality predicate to use (default [(=)]) - @since 0.5 *) +(** Is the value a member of the sequence? + @param eq the equality predicate to use (default [(=)]) + @since 0.5 *) val find : ('a -> 'b option) -> 'a t -> 'b option - (** Find the first element on which the function doesn't return [None] - @since 0.5 *) +(** Find the first element on which the function doesn't return [None] + @since 0.5 *) val length : 'a t -> int - (** How long is the sequence? Forces the sequence. *) +(** How long is the sequence? Forces the sequence. *) val is_empty : 'a t -> bool - (** Is the sequence empty? Forces the sequence. *) +(** Is the sequence empty? Forces the sequence. *) (** {2 Transform a sequence} *) val filter : ('a -> bool) -> 'a t -> 'a t - (** Filter on elements of the sequence *) +(** Filter on elements of the sequence *) val append : 'a t -> 'a t -> 'a t - (** Append two sequences. Iterating on the result is like iterating - on the first, then on the second. *) +(** Append two sequences. Iterating on the result is like iterating + on the first, then on the second. *) val concat : 'a t t -> 'a t - (** Concatenate a sequence of sequences into one sequence. *) +(** Concatenate a sequence of sequences into one sequence. *) val flatten : 'a t t -> 'a t - (** Alias for {!concat} *) +(** Alias for {!concat} *) val flatMap : ('a -> 'b t) -> 'a t -> 'b t - (** @deprecated use {!flat_map} since NEXT_RELEASE *) +(** @deprecated use {!flat_map} since NEXT_RELEASE *) val flat_map : ('a -> 'b t) -> 'a t -> 'b t - (** Monadic bind. Intuitively, it applies the function to every element of the - initial sequence, and calls {!concat}. - @since 0.5 *) +(** Monadic bind. Intuitively, it applies the function to every + element of the initial sequence, and calls {!concat}. + @since 0.5 *) val fmap : ('a -> 'b option) -> 'a t -> 'b t - (** @deprecated use {!filter_map} since NEXT_RELEASE *) +(** @deprecated use {!filter_map} since NEXT_RELEASE *) val filter_map : ('a -> 'b option) -> 'a t -> 'b t - (** Map and only keep non-[None] elements - @since 0.5 *) +(** Map and only keep non-[None] elements + @since 0.5 *) val intersperse : 'a -> 'a t -> 'a t - (** Insert the single element between every element of the sequence *) +(** Insert the single element between every element of the sequence *) (** {2 Caching} *) val persistent : 'a t -> 'a t - (** Iterate on the sequence, storing elements in an efficient internal 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! *) +(** Iterate on the sequence, storing elements in an efficient internal 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! *) val persistent_lazy : 'a t -> 'a t - (** Lazy version of {!persistent}. When calling [persistent_lazy s], - a new sequence [s'] is immediately returned (without actually consuming - [s]) in constant time; the first time [s'] is iterated on, - it also consumes [s] and caches its content into a inner data - structure that will back [s'] for future iterations. +(** Lazy version of {!persistent}. When calling [persistent_lazy s], + a new sequence [s'] is immediately returned (without actually consuming + [s]) in constant time; the first time [s'] is iterated on, + it also consumes [s] and caches its content into a inner data + structure that will back [s'] for future iterations. - {b warning}: on the first traversal of [s'], if the traversal - is interrupted prematurely ({!take}, etc.) then [s'] will not be - memorized, and the next call to [s'] will traverse [s] again. *) + {b warning}: on the first traversal of [s'], if the traversal + is interrupted prematurely ({!take}, etc.) then [s'] will not be + memorized, and the next call to [s'] will traverse [s] again. *) (** {2 Misc} *) val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t - (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. - It iterates on elements of the argument sequence immediately, - before it sorts them. *) +(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. + It iterates on elements of the argument sequence immediately, + before it sorts them. *) val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t - (** Sort the sequence and remove duplicates. Eager, same as [sort] *) +(** Sort the sequence and remove duplicates. Eager, same as [sort] *) val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t - (** Group equal consecutive elements. - @deprecated use {!group_succ_by} *) +(** Group equal consecutive elements. + @deprecated use {!group_succ_by} *) val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t - (** Group equal consecutive elements. - Synonym to {!group}. - @since NEXT_RELEASE *) +(** Group equal consecutive elements. + Synonym to {!group}. + @since NEXT_RELEASE *) val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> - 'a t -> 'a list t - (** Group equal elements, disregarding their order of appearance. - The result sequence is traversable as many times as required. - @since NEXT_RELEASE *) + 'a t -> 'a list t +(** Group equal elements, disregarding their order of appearance. + The result sequence is traversable as many times as required. + @since NEXT_RELEASE *) val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t - (** Remove consecutive duplicate elements. Basically this is - like [fun seq -> map List.hd (group seq)]. *) +(** Remove consecutive duplicate elements. Basically this is + like [fun seq -> map List.hd (group seq)]. *) val product : 'a t -> 'b t -> ('a * 'b) t - (** Cartesian product of the sequences. When calling [product a b], - the caller {b MUST} ensure that [b] can be traversed as many times - as required (several times), possibly by calling {!persistent} on it - beforehand. *) +(** Cartesian product of the sequences. When calling [product a b], + the caller {b MUST} ensure that [b] can be traversed as many times + as required (several times), possibly by calling {!persistent} on it + beforehand. *) val product2 : 'a t -> 'b t -> ('a, 'b) t2 - (** Binary version of {!product}. Same requirements. - @since 0.5 *) +(** Binary version of {!product}. Same requirements. + @since 0.5 *) val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t - (** [join ~join_row a b] combines every element of [a] with every - element of [b] using [join_row]. If [join_row] returns None, then - the two elements do not combine. Assume that [b] allows for multiple - iterations. *) +(** [join ~join_row a b] combines every element of [a] with every + element of [b] using [join_row]. If [join_row] returns None, then + the two elements do not combine. Assume that [b] allows for multiple + iterations. *) val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t - (** [unfoldr f b] will apply [f] to [b]. If it - yields [Some (x,b')] then [x] is returned - and unfoldr recurses with [b']. *) +(** [unfoldr f b] will apply [f] to [b]. If it + yields [Some (x,b')] then [x] is returned + and unfoldr recurses with [b']. *) val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t - (** Sequence of intermediate results *) +(** Sequence of intermediate results *) 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 *) +(** 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 option - (** Min element of the sequence, using the given comparison function. - see {!max} for more details. *) +(** Min element of the sequence, using the given comparison function. + see {!max} for more details. *) val head : 'a t -> 'a option - (** First element, if any, otherwise [None] - @since 0.5.1 *) +(** First element, if any, otherwise [None] + @since 0.5.1 *) val head_exn : 'a t -> 'a - (** First element, if any, fails - @raise Invalid_argument if the sequence is empty - @since 0.5.1 *) +(** First element, if any, fails + @raise Invalid_argument if the sequence is empty + @since 0.5.1 *) val take : int -> 'a t -> 'a t - (** Take at most [n] elements from the sequence. Works on infinite - sequences. *) +(** Take at most [n] elements from the sequence. Works on infinite + sequences. *) val take_while : ('a -> bool) -> 'a t -> 'a t - (** Take elements while they satisfy the predicate, then stops iterating. - Will work on an infinite sequence [s] if the predicate is false for at - least one element of [s]. *) +(** Take elements while they satisfy the predicate, then stops iterating. + Will work on an infinite sequence [s] if the predicate is false for at + least one element of [s]. *) val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a - (** Folds over elements of the sequence, stopping early if the accumulator - returns [('a, `Stop)] - @since 0.5.5 *) +(** Folds over elements of the sequence, stopping early if the accumulator + returns [('a, `Stop)] + @since 0.5.5 *) val drop : int -> 'a t -> 'a t - (** Drop the [n] first elements of the sequence. Lazy. *) +(** Drop the [n] first elements of the sequence. Lazy. *) val drop_while : ('a -> bool) -> 'a t -> 'a t - (** Predicate version of {!drop} *) +(** Predicate version of {!drop} *) val rev : 'a t -> 'a t - (** Reverse the sequence. O(n) memory and time, needs the - sequence to be finite. The result is persistent and does - not depend on the input being repeatable. *) +(** Reverse the sequence. O(n) memory and time, needs the + sequence to be finite. The result is persistent and does + not depend on the input being repeatable. *) (** {2 Binary sequences} *) @@ -313,7 +291,7 @@ val zip : ('a, 'b) t2 -> ('a * 'b) t val unzip : ('a * 'b) t -> ('a, 'b) t2 val zip_i : 'a t -> (int, 'a) t2 - (** Zip elements of the sequence with their index in the sequence *) +(** Zip elements of the sequence with their index in the sequence *) val fold2 : ('c -> 'a -> 'b -> 'c) -> 'c -> ('a, 'b) t2 -> 'c @@ -322,17 +300,17 @@ val iter2 : ('a -> 'b -> unit) -> ('a, 'b) t2 -> unit val map2 : ('a -> 'b -> 'c) -> ('a, 'b) t2 -> 'c t val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a, 'b) t2 -> ('c, 'd) t2 - (** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *) +(** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *) (** {2 Basic data structures converters} *) val to_list : 'a t -> 'a list - (** Convert the sequence into a list. Preserves order of elements. - This function is tail-recursive, but consumes 2*n memory. - If order doesn't matter to you, consider {!to_rev_list}. *) +(** Convert the sequence into a list. Preserves order of elements. + This function is tail-recursive, but consumes 2*n memory. + If order doesn't matter to you, consider {!to_rev_list}. *) val to_rev_list : 'a t -> 'a list - (** Get the list of the reversed sequence (more efficient than {!to_list}) *) +(** Get the list of the reversed sequence (more efficient than {!to_list}) *) val of_list : 'a list -> 'a t @@ -342,65 +320,65 @@ val on_list : ('a t -> 'b t) -> 'a list -> 'b list *) val to_opt : 'a t -> 'a option - (** Alias to {!head} - @since 0.5.1 *) +(** Alias to {!head} + @since 0.5.1 *) val to_array : 'a t -> 'a array - (** Convert to an array. Currently not very efficient because - an intermediate list is used. *) +(** Convert to an array. Currently not very efficient because + an intermediate list is used. *) val of_array : 'a array -> 'a t val of_array_i : 'a array -> (int * 'a) t - (** Elements of the array, with their index *) +(** Elements of the array, with their index *) val of_array2 : 'a array -> (int, 'a) t2 val array_slice : 'a array -> int -> int -> 'a t - (** [array_slice a i j] Sequence of elements whose indexes range - from [i] to [j] *) +(** [array_slice a i j] Sequence of elements whose indexes range + from [i] to [j] *) val of_opt : 'a option -> 'a t - (** Iterate on 0 or 1 values. - @since 0.5.1 *) +(** Iterate on 0 or 1 values. + @since 0.5.1 *) val of_stream : 'a Stream.t -> 'a t - (** Sequence of elements of a stream (usable only once) *) +(** Sequence of elements of a stream (usable only once) *) val to_stream : 'a t -> 'a Stream.t - (** Convert to a stream. linear in memory and time (a copy is made in memory) *) +(** Convert to a stream. linear in memory and time (a copy is made in memory) *) val to_stack : 'a Stack.t -> 'a t -> unit - (** Push elements of the sequence on the stack *) +(** Push elements of the sequence on the stack *) val of_stack : 'a Stack.t -> 'a t - (** Sequence of elements of the stack (same order as [Stack.iter]) *) +(** Sequence of elements of the stack (same order as [Stack.iter]) *) val to_queue : 'a Queue.t -> 'a t -> unit - (** Push elements of the sequence into the queue *) +(** Push elements of the sequence into the queue *) val of_queue : 'a Queue.t -> 'a t - (** Sequence of elements contained in the queue, FIFO order *) +(** Sequence of elements contained in the queue, FIFO order *) val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit - (** Add elements of the sequence to the hashtable, with - Hashtbl.add *) +(** Add elements of the sequence to the hashtable, with + Hashtbl.add *) val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit - (** Add elements of the sequence to the hashtable, with - Hashtbl.replace (erases conflicting bindings) *) +(** Add elements of the sequence to the hashtable, with + Hashtbl.replace (erases conflicting bindings) *) val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t - (** Build a hashtable from a sequence of key/value pairs *) +(** Build a hashtable from a sequence of key/value pairs *) val to_hashtbl2 : ('a, 'b) t2 -> ('a, 'b) Hashtbl.t - (** Build a hashtable from a sequence of key/value pairs *) +(** Build a hashtable from a sequence of key/value pairs *) val of_hashtbl : ('a, 'b) Hashtbl.t -> ('a * 'b) t - (** Sequence of key/value pairs from the hashtable *) +(** Sequence of key/value pairs from the hashtable *) val of_hashtbl2 : ('a, 'b) Hashtbl.t -> ('a, 'b) t2 - (** Sequence of key/value pairs from the hashtable *) +(** Sequence of key/value pairs from the hashtable *) val hashtbl_keys : ('a, 'b) Hashtbl.t -> 'a t val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b t @@ -409,55 +387,55 @@ val of_str : string -> char t val to_str : char t -> string val concat_str : string t -> string - (** Concatenate strings together, eagerly. - Also see {!intersperse} to add a separator. - @since 0.5 *) +(** Concatenate strings together, eagerly. + Also see {!intersperse} to add a separator. + @since 0.5 *) exception OneShotSequence - (** Raised when the user tries to iterate several times on - a transient iterator *) +(** Raised when the user tries to iterate several times on + a transient iterator *) val of_in_channel : in_channel -> char t - (** Iterates on characters of the input (can block when one - iterates over the sequence). If you need to iterate - several times on this sequence, use {!persistent}. - @raise OneShotSequence when used more than once. *) +(** Iterates on characters of the input (can block when one + iterates over the sequence). If you need to iterate + several times on this sequence, use {!persistent}. + @raise OneShotSequence when used more than once. *) val to_buffer : char t -> Buffer.t -> unit - (** Copy content of the sequence into the buffer *) +(** 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. Also see - {!(--)} for an infix version. *) +(** 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 *) +(** Iterator on decreasing integers in [stop...start] by steps -1. + See {!(--^)} for an infix version *) val bools : bool t - (** Iterates on [true] and [false] - @since NEXT_RELEASE *) +(** Iterates on [true] and [false] + @since NEXT_RELEASE *) 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. *) +(** Convert the given set to a sequence. The set module must be provided. *) 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 *) +(** Convert the sequence to a set, given the proper set module *) type 'a gen = unit -> 'a option type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist] val of_gen : 'a gen -> 'a t - (** Traverse eagerly the generator and build a sequence from it *) +(** 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. *) +(** Make the sequence persistent (O(n)) and then iterate on it. Eager. *) val of_klist : 'a klist -> 'a t - (** Iterate on the lazy list *) +(** Iterate on the lazy list *) val to_klist : 'a t -> 'a klist - (** Make the sequence persistent and then iterate on it. Eager. *) +(** Make the sequence persistent and then iterate on it. Eager. *) (** {2 Functorial conversions between sets and sequences} *) @@ -500,48 +478,48 @@ end (** {2 Infinite sequences of random values} *) val random_int : int -> int t - (** Infinite sequence of random integers between 0 and - the given higher bound (see Random.int) *) +(** Infinite sequence of random integers between 0 and + the given higher bound (see Random.int) *) val random_bool : bool t - (** Infinite sequence of random bool values *) +(** Infinite sequence of random bool values *) val random_float : float -> float t val random_array : 'a array -> 'a t - (** Sequence of choices of an element in the array *) +(** Sequence of choices of an element in the array *) val random_list : 'a list -> 'a t - (** Infinite sequence of random elements of the list. Basically the - same as {!random_array}. *) +(** Infinite sequence of random elements of the list. Basically the + same as {!random_array}. *) (** {2 Infix functions} *) module Infix : sig val (--) : int -> int -> int t - (** [a -- b] is the range of integers from [a] to [b], both included, - in increasing order. It will therefore be empty if [a > b]. *) + (** [a -- b] is the range of integers from [a] to [b], both included, + in increasing order. It will therefore be empty if [a > b]. *) 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]. *) + (** [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]. *) val (>>=) : 'a t -> ('a -> 'b t) -> 'b t - (** Monadic bind (infix version of {!flat_map} - @since 0.5 *) + (** Monadic bind (infix version of {!flat_map} + @since 0.5 *) val (>|=) : 'a t -> ('a -> 'b) -> 'b t - (** Infix version of {!map} - @since 0.5 *) + (** Infix version of {!map} + @since 0.5 *) val (<*>) : ('a -> 'b) t -> 'a t -> 'b t - (** Applicative operator (product+application) - @since 0.5 *) + (** Applicative operator (product+application) + @since 0.5 *) val (<+>) : 'a t -> 'a t -> 'a t - (** Concatenation of sequences - @since 0.5 *) + (** Concatenation of sequences + @since 0.5 *) end include module type of Infix @@ -549,46 +527,46 @@ include module type of Infix (** {2 Pretty printing of sequences} *) val pp_seq : ?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. *) + 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_buf : ?sep:string -> (Buffer.t -> 'a -> unit) -> - Buffer.t -> 'a t -> unit - (** Print into a buffer *) + Buffer.t -> 'a t -> unit +(** Print into a buffer *) val to_string : ?sep:string -> ('a -> string) -> 'a t -> string - (** Print into a string *) +(** Print into a string *) (** {2 Basic IO} -Very basic interface to manipulate files as sequence of chunks/lines. The -sequences take care of opening and closing files properly; every time -one iterates over a sequence, the file is opened/closed again. + Very basic interface to manipulate files as sequence of chunks/lines. The + sequences take care of opening and closing files properly; every time + one iterates over a sequence, the file is opened/closed again. -Example: copy a file ["a"] into file ["b"], removing blank lines: + Example: copy a file ["a"] into file ["b"], removing blank lines: -{[ - Sequence.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");; -]} + {[ + Sequence.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");; + ]} -By chunks of [4096] bytes: + By chunks of [4096] bytes: -{[ - Sequence.IO.(chunks_of ~size:4096 "a" |> write_to "b");; -]} + {[ + Sequence.IO.(chunks_of ~size:4096 "a" |> write_to "b");; + ]} -Read the lines of a file into a list: + Read the lines of a file into a list: -{[ - Sequence.IO.lines "a" |> Sequence.to_list -]} + {[ + Sequence.IO.lines "a" |> Sequence.to_list + ]} -@since 0.5.1 *) + @since 0.5.1 *) module IO : sig val lines_of : ?mode:int -> ?flags:open_flag list -> - string -> string t + string -> string t (** [lines_of filename] reads all lines of the given file. It raises the same exception as would opening the file and read from it, except from [End_of_file] (which is caught). The file is {b always} properly @@ -599,28 +577,28 @@ module IO : sig @param flags default: [[Open_rdonly]] *) val chunks_of : ?mode:int -> ?flags:open_flag list -> ?size:int -> - string -> string t + string -> string t (** Read chunks of the given [size] from the file. The last chunk might be smaller. Behaves like {!lines_of} regarding errors and options. Every time the sequence is iterated on, the file is opened again, so different iterations might return different results *) val write_to : ?mode:int -> ?flags:open_flag list -> - string -> string t -> unit + string -> string t -> unit (** [write_to filename seq] writes all strings from [seq] into the given file. It takes care of opening and closing the file. @param mode default [0o644] @param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *) val write_bytes_to : ?mode:int -> ?flags:open_flag list -> - string -> Bytes.t t -> unit + string -> Bytes.t t -> unit (** @since 0.5.4 *) val write_lines : ?mode:int -> ?flags:open_flag list -> - string -> string t -> unit + string -> string t -> unit (** Same as {!write_to}, but intercales ['\n'] between each string *) val write_bytes_lines : ?mode:int -> ?flags:open_flag list -> - string -> Bytes.t t -> unit + string -> Bytes.t t -> unit (** @since 0.5.4 *) end diff --git a/sequenceLabels.mli b/sequenceLabels.mli index ca4bf90..08f9a71 100644 --- a/sequenceLabels.mli +++ b/sequenceLabels.mli @@ -1,263 +1,239 @@ -(* -copyright (c) 2013, simon cruanes -all rights reserved. -redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +(* This file is free software, part of sequence. See file "license" for more details. *) -redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. redistributions in binary -form must reproduce the above copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other materials provided with -the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*) (** {1 Simple and Efficient Iterators} -Version of {!Sequence} with labels + Version of {!Sequence} with labels -@since 0.5.5 *) + @since 0.5.5 *) type +'a t = ('a -> unit) -> unit - (** A sequence of values of type ['a]. If you give it a function ['a -> unit] - it will be applied to every element of the sequence successively. *) +(** A sequence of values of type ['a]. If you give it a function ['a -> unit] + it will be applied to every element of the sequence successively. *) type +'a sequence = 'a t type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit - (** Sequence of pairs of values of type ['a] and ['b]. *) +(** Sequence of pairs of values of type ['a] and ['b]. *) (** {2 Build a sequence} *) val from_iter : (('a -> unit) -> unit) -> 'a t - (** Build a sequence from a iter function *) +(** Build a sequence from a iter function *) val from_fun : (unit -> 'a option) -> 'a t - (** Call the function repeatedly until it returns None. This - sequence is transient, use {!persistent} if needed! *) +(** Call the function repeatedly until it returns None. This + sequence is transient, use {!persistent} if needed! *) val empty : 'a t - (** Empty sequence. It contains no element. *) +(** Empty sequence. It contains no element. *) val singleton : 'a -> 'a t - (** Singleton sequence, with exactly one element. *) +(** Singleton sequence, with exactly one element. *) val doubleton : 'a -> 'a -> 'a t - (** Sequence with exactly two elements *) +(** Sequence with exactly two elements *) val cons : 'a -> 'a t -> 'a t - (** [cons x l] yields [x], then yields from [l]. - Same as [append (singleton x) l] *) +(** [cons x l] yields [x], then yields from [l]. + Same as [append (singleton x) l] *) val snoc : 'a t -> 'a -> 'a t - (** Same as {!cons} but yields the element after iterating on [l] *) +(** Same as {!cons} but yields the element after iterating on [l] *) val return : 'a -> 'a t - (** Synonym to {!singleton} *) +(** Synonym to {!singleton} *) val pure : 'a -> 'a t - (** Synonym to {!singleton} *) +(** Synonym to {!singleton} *) val repeat : 'a -> 'a t - (** Infinite sequence of the same element. You may want to look - at {!take} and the likes if you iterate on it. *) +(** Infinite sequence of the same element. You may want to look + at {!take} and the likes if you iterate on it. *) val iterate : ('a -> 'a) -> 'a -> 'a t - (** [iterate f x] is the infinite sequence [x, f(x), f(f(x)), ...] *) +(** [iterate f x] is the infinite sequence [x, f(x), f(f(x)), ...] *) val forever : (unit -> 'b) -> 'b t - (** Sequence that calls the given function to produce elements. - The sequence may be transient (depending on the function), and definitely - is infinite. You may want to use {!take} and {!persistent}. *) +(** Sequence that calls the given function to produce elements. + The sequence may be transient (depending on the function), and definitely + is infinite. You may want to use {!take} and {!persistent}. *) val cycle : 'a t -> 'a t - (** Cycle forever through the given sequence. Assume the given sequence can - be traversed any amount of times (not transient). This yields an - infinite sequence, you should use something like {!take} not to loop - forever. *) +(** Cycle forever through the given sequence. Assume the given sequence can + be traversed any amount of times (not transient). This yields an + infinite sequence, you should use something like {!take} not to loop + forever. *) (** {2 Consume a sequence} *) val iter : f:('a -> unit) -> 'a t -> unit - (** Consume the sequence, passing all its arguments to the function. - Basically [iter f seq] is just [seq f]. *) +(** Consume the sequence, passing all its arguments to the function. + Basically [iter f seq] is just [seq f]. *) val iteri : f:(int -> 'a -> unit) -> 'a t -> unit - (** Iterate on elements and their index in the sequence *) +(** Iterate on elements and their index in the sequence *) val fold : f:('a -> 'b -> 'a) -> init:'a -> 'b t -> 'a - (** Fold over elements of the sequence, consuming it *) +(** Fold over elements of the sequence, consuming it *) val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a - (** Fold over elements of the sequence and their index, consuming it *) +(** Fold over elements of the sequence and their index, consuming it *) val map : f:('a -> 'b) -> 'a t -> 'b t - (** Map objects of the sequence into other elements, lazily *) +(** Map objects of the sequence into other elements, lazily *) val mapi : f:(int -> 'a -> 'b) -> 'a t -> 'b t - (** Map objects, along with their index in the sequence *) +(** Map objects, along with their index in the sequence *) val for_all : f:('a -> bool) -> 'a t -> bool - (** Do all elements satisfy the predicate? *) +(** Do all elements satisfy the predicate? *) val exists : f:('a -> bool) -> 'a t -> bool - (** Exists there some element satisfying the predicate? *) +(** Exists there some element satisfying the predicate? *) val mem : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> bool - (** Is the value a member of the sequence? - @param eq the equality predicate to use (default [(=)]) *) +(** Is the value a member of the sequence? + @param eq the equality predicate to use (default [(=)]) *) val find : f:('a -> 'b option) -> 'a t -> 'b option - (** Find the first element on which the function doesn't return [None] *) +(** Find the first element on which the function doesn't return [None] *) val length : 'a t -> int - (** How long is the sequence? Forces the sequence. *) +(** How long is the sequence? Forces the sequence. *) val is_empty : 'a t -> bool - (** Is the sequence empty? Forces the sequence. *) +(** Is the sequence empty? Forces the sequence. *) (** {2 Transform a sequence} *) val filter : f:('a -> bool) -> 'a t -> 'a t - (** Filter on elements of the sequence *) +(** Filter on elements of the sequence *) val append : 'a t -> 'a t -> 'a t - (** Append two sequences. Iterating on the result is like iterating - on the first, then on the second. *) +(** Append two sequences. Iterating on the result is like iterating + on the first, then on the second. *) val concat : 'a t t -> 'a t - (** Concatenate a sequence of sequences into one sequence. *) +(** Concatenate a sequence of sequences into one sequence. *) val flatten : 'a t t -> 'a t - (** Alias for {!concat} *) +(** Alias for {!concat} *) val flatMap : f:('a -> 'b t) -> 'a t -> 'b t - (** Monadic bind. Intuitively, it applies the function to every element of the - initial sequence, and calls {!concat}. - @deprecated use {!flat_map} *) +(** @deprecated use {!flat_map} *) val flat_map : f:('a -> 'b t) -> 'a t -> 'b t - (** Alias to {!flatMap} with a more explicit name *) +(** Alias to {!flatMap} with a more explicit name *) val fmap : f:('a -> 'b option) -> 'a t -> 'b t - (** Specialized version of {!flatMap} for options. - @deprecated use {!filter_map} *) +(** @deprecated use {!filter_map} *) val filter_map : f:('a -> 'b option) -> 'a t -> 'b t - (** Alias to {!fmap} with a more explicit name *) +(** Alias to {!fmap} with a more explicit name *) val intersperse : x:'a -> 'a t -> 'a t - (** Insert the single element between every element of the sequence *) +(** Insert the single element between every element of the sequence *) (** {2 Caching} *) val persistent : 'a t -> 'a t - (** Iterate on the sequence, storing elements in an efficient internal 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! *) +(** Iterate on the sequence, storing elements in an efficient internal 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! *) val persistent_lazy : 'a t -> 'a t - (** Lazy version of {!persistent}. When calling [persistent_lazy s], - a new sequence [s'] is immediately returned (without actually consuming - [s]) in constant time; the first time [s'] is iterated on, - it also consumes [s] and caches its content into a inner data - structure that will back [s'] for future iterations. +(** Lazy version of {!persistent}. When calling [persistent_lazy s], + a new sequence [s'] is immediately returned (without actually consuming + [s]) in constant time; the first time [s'] is iterated on, + it also consumes [s] and caches its content into a inner data + structure that will back [s'] for future iterations. - {b warning}: on the first traversal of [s'], if the traversal - is interrupted prematurely ({!take}, etc.) then [s'] will not be - memorized, and the next call to [s'] will traverse [s] again. *) + {b warning}: on the first traversal of [s'], if the traversal + is interrupted prematurely ({!take}, etc.) then [s'] will not be + memorized, and the next call to [s'] will traverse [s] again. *) (** {2 Misc} *) val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t - (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. - It iterates on elements of the argument sequence immediately, - before it sorts them. *) +(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. + It iterates on elements of the argument sequence immediately, + before it sorts them. *) val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t - (** Sort the sequence and remove duplicates. Eager, same as [sort] *) +(** Sort the sequence and remove duplicates. Eager, same as [sort] *) val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t - (** Group equal consecutive elements. *) +(** Group equal consecutive elements. *) val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t - (** Remove consecutive duplicate elements. Basically this is - like [fun seq -> map List.hd (group seq)]. *) +(** Remove consecutive duplicate elements. Basically this is + like [fun seq -> map List.hd (group seq)]. *) val product : 'a t -> 'b t -> ('a * 'b) t - (** Cartesian product of the sequences. When calling [product a b], - the caller {b MUST} ensure that [b] can be traversed as many times - as required (several times), possibly by calling {!persistent} on it - beforehand. *) +(** Cartesian product of the sequences. When calling [product a b], + the caller {b MUST} ensure that [b] can be traversed as many times + as required (several times), possibly by calling {!persistent} on it + beforehand. *) val product2 : 'a t -> 'b t -> ('a, 'b) t2 - (** Binary version of {!product}. Same requirements. *) +(** Binary version of {!product}. Same requirements. *) val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t - (** [join ~join_row a b] combines every element of [a] with every - element of [b] using [join_row]. If [join_row] returns None, then - the two elements do not combine. Assume that [b] allows for multiple - iterations. *) +(** [join ~join_row a b] combines every element of [a] with every + element of [b] using [join_row]. If [join_row] returns None, then + the two elements do not combine. Assume that [b] allows for multiple + iterations. *) val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t - (** [unfoldr f b] will apply [f] to [b]. If it - yields [Some (x,b')] then [x] is returned - and unfoldr recurses with [b']. *) +(** [unfoldr f b] will apply [f] to [b]. If it + yields [Some (x,b')] then [x] is returned + and unfoldr recurses with [b']. *) val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t - (** Sequence of intermediate results *) +(** Sequence of intermediate results *) 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 *) +(** 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 option - (** Min element of the sequence, using the given comparison function. - see {!max} for more details. *) +(** Min element of the sequence, using the given comparison function. + see {!max} for more details. *) val head : 'a t -> 'a option - (** First element, if any, otherwise [None] *) +(** First element, if any, otherwise [None] *) val head_exn : 'a t -> 'a - (** First element, if any, fails - @raise Invalid_argument if the sequence is empty *) +(** First element, if any, fails + @raise Invalid_argument if the sequence is empty *) val take : int -> 'a t -> 'a t - (** Take at most [n] elements from the sequence. Works on infinite - sequences. *) +(** Take at most [n] elements from the sequence. Works on infinite + sequences. *) val take_while : f:('a -> bool) -> 'a t -> 'a t - (** Take elements while they satisfy the predicate, then stops iterating. - Will work on an infinite sequence [s] if the predicate is false for at - least one element of [s]. *) +(** Take elements while they satisfy the predicate, then stops iterating. + Will work on an infinite sequence [s] if the predicate is false for at + least one element of [s]. *) val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a - (** Folds over elements of the sequence, stopping early if the accumulator - returns [('a, `Stop)] *) +(** Folds over elements of the sequence, stopping early if the accumulator + returns [('a, `Stop)] *) val drop : int -> 'a t -> 'a t - (** Drop the [n] first elements of the sequence. Lazy. *) +(** Drop the [n] first elements of the sequence. Lazy. *) val drop_while : f:('a -> bool) -> 'a t -> 'a t - (** Predicate version of {!drop} *) +(** Predicate version of {!drop} *) val rev : 'a t -> 'a t - (** Reverse the sequence. O(n) memory and time, needs the - sequence to be finite. The result is persistent and does - not depend on the input being repeatable. *) +(** Reverse the sequence. O(n) memory and time, needs the + sequence to be finite. The result is persistent and does + not depend on the input being repeatable. *) (** {2 Binary sequences} *) @@ -272,7 +248,7 @@ val zip : ('a, 'b) t2 -> ('a * 'b) t val unzip : ('a * 'b) t -> ('a, 'b) t2 val zip_i : 'a t -> (int, 'a) t2 - (** Zip elements of the sequence with their index in the sequence *) +(** Zip elements of the sequence with their index in the sequence *) val fold2 : f:('c -> 'a -> 'b -> 'c) -> init:'c -> ('a, 'b) t2 -> 'c @@ -281,17 +257,17 @@ val iter2 : f:('a -> 'b -> unit) -> ('a, 'b) t2 -> unit val map2 : f:('a -> 'b -> 'c) -> ('a, 'b) t2 -> 'c t val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a, 'b) t2 -> ('c, 'd) t2 - (** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *) +(** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *) (** {2 Basic data structures converters} *) val to_list : 'a t -> 'a list - (** Convert the sequence into a list. Preserves order of elements. - This function is tail-recursive, but consumes 2*n memory. - If order doesn't matter to you, consider {!to_rev_list}. *) +(** Convert the sequence into a list. Preserves order of elements. + This function is tail-recursive, but consumes 2*n memory. + If order doesn't matter to you, consider {!to_rev_list}. *) val to_rev_list : 'a t -> 'a list - (** Get the list of the reversed sequence (more efficient than {!to_list}) *) +(** Get the list of the reversed sequence (more efficient than {!to_list}) *) val of_list : 'a list -> 'a t @@ -299,63 +275,63 @@ val on_list : ('a t -> 'b t) -> 'a list -> 'b list (** [on_list f l] is equivalent to [to_list @@ f @@ of_list l]. *) val to_opt : 'a t -> 'a option - (** Alias to {!head} *) +(** Alias to {!head} *) val to_array : 'a t -> 'a array - (** Convert to an array. Currently not very efficient because - an intermediate list is used. *) +(** Convert to an array. Currently not very efficient because + an intermediate list is used. *) val of_array : 'a array -> 'a t val of_array_i : 'a array -> (int * 'a) t - (** Elements of the array, with their index *) +(** Elements of the array, with their index *) val of_array2 : 'a array -> (int, 'a) t2 val array_slice : 'a array -> int -> int -> 'a t - (** [array_slice a i j] Sequence of elements whose indexes range - from [i] to [j] *) +(** [array_slice a i j] Sequence of elements whose indexes range + from [i] to [j] *) val of_opt : 'a option -> 'a t - (** Iterate on 0 or 1 values. *) +(** Iterate on 0 or 1 values. *) val of_stream : 'a Stream.t -> 'a t - (** Sequence of elements of a stream (usable only once) *) +(** Sequence of elements of a stream (usable only once) *) val to_stream : 'a t -> 'a Stream.t - (** Convert to a stream. linear in memory and time (a copy is made in memory) *) +(** Convert to a stream. linear in memory and time (a copy is made in memory) *) val to_stack : 'a Stack.t -> 'a t -> unit - (** Push elements of the sequence on the stack *) +(** Push elements of the sequence on the stack *) val of_stack : 'a Stack.t -> 'a t - (** Sequence of elements of the stack (same order as [Stack.iter]) *) +(** Sequence of elements of the stack (same order as [Stack.iter]) *) val to_queue : 'a Queue.t -> 'a t -> unit - (** Push elements of the sequence into the queue *) +(** Push elements of the sequence into the queue *) val of_queue : 'a Queue.t -> 'a t - (** Sequence of elements contained in the queue, FIFO order *) +(** Sequence of elements contained in the queue, FIFO order *) val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit - (** Add elements of the sequence to the hashtable, with - Hashtbl.add *) +(** Add elements of the sequence to the hashtable, with + Hashtbl.add *) val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit - (** Add elements of the sequence to the hashtable, with - Hashtbl.replace (erases conflicting bindings) *) +(** Add elements of the sequence to the hashtable, with + Hashtbl.replace (erases conflicting bindings) *) val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t - (** Build a hashtable from a sequence of key/value pairs *) +(** Build a hashtable from a sequence of key/value pairs *) val to_hashtbl2 : ('a, 'b) t2 -> ('a, 'b) Hashtbl.t - (** Build a hashtable from a sequence of key/value pairs *) +(** Build a hashtable from a sequence of key/value pairs *) val of_hashtbl : ('a, 'b) Hashtbl.t -> ('a * 'b) t - (** Sequence of key/value pairs from the hashtable *) +(** Sequence of key/value pairs from the hashtable *) val of_hashtbl2 : ('a, 'b) Hashtbl.t -> ('a, 'b) t2 - (** Sequence of key/value pairs from the hashtable *) +(** Sequence of key/value pairs from the hashtable *) val hashtbl_keys : ('a, 'b) Hashtbl.t -> 'a t val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b t @@ -364,50 +340,50 @@ val of_str : string -> char t val to_str : char t -> string val concat_str : string t -> string - (** Concatenate strings together, eagerly. - Also see {!intersperse} to add a separator. *) +(** Concatenate strings together, eagerly. + Also see {!intersperse} to add a separator. *) exception OneShotSequence - (** Raised when the user tries to iterate several times on - a transient iterator *) +(** Raised when the user tries to iterate several times on + a transient iterator *) val of_in_channel : in_channel -> char t - (** Iterates on characters of the input (can block when one - iterates over the sequence). If you need to iterate - several times on this sequence, use {!persistent}. - @raise OneShotSequence when used more than once. *) +(** Iterates on characters of the input (can block when one + iterates over the sequence). If you need to iterate + several times on this sequence, use {!persistent}. + @raise OneShotSequence when used more than once. *) val to_buffer : char t -> Buffer.t -> unit - (** Copy content of the sequence into the buffer *) +(** 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. Also see - {!(--)} for an infix version. *) +(** 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 *) +(** 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. *) +(** Convert the given set to a sequence. The set module must be provided. *) 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 *) +(** Convert the sequence to a set, given the proper set module *) type 'a gen = unit -> 'a option type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist] val of_gen : 'a gen -> 'a t - (** Traverse eagerly the generator and build a sequence from it *) +(** 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. *) +(** Make the sequence persistent (O(n)) and then iterate on it. Eager. *) val of_klist : 'a klist -> 'a t - (** Iterate on the lazy list *) +(** Iterate on the lazy list *) val to_klist : 'a t -> 'a klist - (** Make the sequence persistent and then iterate on it. Eager. *) +(** Make the sequence persistent and then iterate on it. Eager. *) (** {2 Functorial conversions between sets and sequences} *) @@ -450,44 +426,44 @@ end (** {2 Infinite sequences of random values} *) val random_int : int -> int t - (** Infinite sequence of random integers between 0 and - the given higher bound (see Random.int) *) +(** Infinite sequence of random integers between 0 and + the given higher bound (see Random.int) *) val random_bool : bool t - (** Infinite sequence of random bool values *) +(** Infinite sequence of random bool values *) val random_float : float -> float t val random_array : 'a array -> 'a t - (** Sequence of choices of an element in the array *) +(** Sequence of choices of an element in the array *) val random_list : 'a list -> 'a t - (** Infinite sequence of random elements of the list. Basically the - same as {!random_array}. *) +(** Infinite sequence of random elements of the list. Basically the + same as {!random_array}. *) (** {2 Infix functions} *) module Infix : sig val (--) : int -> int -> int t - (** [a -- b] is the range of integers from [a] to [b], both included, - in increasing order. It will therefore be empty if [a > b]. *) + (** [a -- b] is the range of integers from [a] to [b], both included, + in increasing order. It will therefore be empty if [a > b]. *) 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]. *) + (** [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]. *) val (>>=) : 'a t -> ('a -> 'b t) -> 'b t - (** Monadic bind (infix version of {!flat_map} *) + (** Monadic bind (infix version of {!flat_map} *) val (>|=) : 'a t -> ('a -> 'b) -> 'b t - (** Infix version of {!map} *) + (** Infix version of {!map} *) val (<*>) : ('a -> 'b) t -> 'a t -> 'b t - (** Applicative operator (product+application) *) + (** Applicative operator (product+application) *) val (<+>) : 'a t -> 'a t -> 'a t - (** Concatenation of sequences *) + (** Concatenation of sequences *) end include module type of Infix @@ -496,46 +472,46 @@ include module type of Infix (** {2 Pretty printing of sequences} *) val pp_seq : ?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. *) + 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_buf : ?sep:string -> (Buffer.t -> 'a -> unit) -> - Buffer.t -> 'a t -> unit - (** Print into a buffer *) + Buffer.t -> 'a t -> unit +(** Print into a buffer *) val to_string : ?sep:string -> ('a -> string) -> 'a t -> string - (** Print into a string *) +(** Print into a string *) (** {2 Basic IO} -Very basic interface to manipulate files as sequence of chunks/lines. The -sequences take care of opening and closing files properly; every time -one iterates over a sequence, the file is opened/closed again. + Very basic interface to manipulate files as sequence of chunks/lines. The + sequences take care of opening and closing files properly; every time + one iterates over a sequence, the file is opened/closed again. -Example: copy a file ["a"] into file ["b"], removing blank lines: + Example: copy a file ["a"] into file ["b"], removing blank lines: -{[ - Sequence.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");; -]} + {[ + Sequence.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");; + ]} -By chunks of [4096] bytes: + By chunks of [4096] bytes: -{[ - Sequence.IO.(chunks_of ~size:4096 "a" |> write_to "b");; -]} + {[ + Sequence.IO.(chunks_of ~size:4096 "a" |> write_to "b");; + ]} -Read the lines of a file into a list: + Read the lines of a file into a list: -{[ - Sequence.IO.lines "a" |> Sequence.to_list -]} + {[ + Sequence.IO.lines "a" |> Sequence.to_list + ]} *) module IO : sig val lines_of : ?mode:int -> ?flags:open_flag list -> - string -> string t + string -> string t (** [lines_of filename] reads all lines of the given file. It raises the same exception as would opening the file and read from it, except from [End_of_file] (which is caught). The file is {b always} properly @@ -546,27 +522,27 @@ module IO : sig @param flags default: [[Open_rdonly]] *) val chunks_of : ?mode:int -> ?flags:open_flag list -> ?size:int -> - string -> string t + string -> string t (** Read chunks of the given [size] from the file. The last chunk might be smaller. Behaves like {!lines_of} regarding errors and options. Every time the sequence is iterated on, the file is opened again, so different iterations might return different results *) val write_to : ?mode:int -> ?flags:open_flag list -> - string -> string t -> unit + string -> string t -> unit (** [write_to filename seq] writes all strings from [seq] into the given file. It takes care of opening and closing the file. @param mode default [0o644] @param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *) val write_bytes_to : ?mode:int -> ?flags:open_flag list -> - string -> Bytes.t t -> unit + string -> Bytes.t t -> unit (** *) val write_lines : ?mode:int -> ?flags:open_flag list -> - string -> string t -> unit + string -> string t -> unit (** Same as {!write_to}, but intercales ['\n'] between each string *) val write_bytes_lines : ?mode:int -> ?flags:open_flag list -> - string -> Bytes.t t -> unit + string -> Bytes.t t -> unit end From 7bc7407ed29c1961691143edb5276920d98d62b7 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 8 Jan 2016 20:45:12 +0100 Subject: [PATCH 10/10] prepare for 0.6 --- _oasis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_oasis b/_oasis index 0324bcd..c5f184f 100644 --- a/_oasis +++ b/_oasis @@ -1,6 +1,6 @@ OASISFormat: 0.4 Name: sequence -Version: 0.5.5 +Version: 0.6 Homepage: https://github.com/c-cube/sequence Authors: Simon Cruanes License: BSD-2-clause