Merge branch 'master' into stable for 0.6

This commit is contained in:
Simon Cruanes 2016-01-08 20:45:39 +01:00
commit 629d538a41
9 changed files with 579 additions and 592 deletions

View file

@ -1,4 +1,4 @@
Copyright (c) 2012, Simon Cruanes Copyright (c) 2012-2016, Simon Cruanes
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

8
META
View file

@ -1,6 +1,6 @@
# OASIS_START # OASIS_START
# DO NOT EDIT (digest: 2f8e4d7fc3cb814610643e4ca5e33697) # DO NOT EDIT (digest: e23210adac78822adc0cf3b47bd47a95)
version = "0.5.5" version = "0.6"
description = "Simple sequence (iterator) datatype and combinators" description = "Simple sequence (iterator) datatype and combinators"
requires = "bytes" requires = "bytes"
archive(byte) = "sequence.cma" archive(byte) = "sequence.cma"
@ -9,7 +9,7 @@ archive(native) = "sequence.cmxa"
archive(native, plugin) = "sequence.cmxs" archive(native, plugin) = "sequence.cmxs"
exists_if = "sequence.cma" exists_if = "sequence.cma"
package "invert" ( package "invert" (
version = "0.5.5" version = "0.6"
description = "Simple sequence (iterator) datatype and combinators" description = "Simple sequence (iterator) datatype and combinators"
requires = "sequence delimcc" requires = "sequence delimcc"
archive(byte) = "invert.cma" archive(byte) = "invert.cma"
@ -20,7 +20,7 @@ package "invert" (
) )
package "bigarray" ( package "bigarray" (
version = "0.5.5" version = "0.6"
description = "Simple sequence (iterator) datatype and combinators" description = "Simple sequence (iterator) datatype and combinators"
requires = "sequence bigarray" requires = "sequence bigarray"
archive(byte) = "bigarray.cma" archive(byte) = "bigarray.cma"

2
_oasis
View file

@ -1,6 +1,6 @@
OASISFormat: 0.4 OASISFormat: 0.4
Name: sequence Name: sequence
Version: 0.5.5 Version: 0.6
Homepage: https://github.com/c-cube/sequence Homepage: https://github.com/c-cube/sequence
Authors: Simon Cruanes Authors: Simon Cruanes
License: BSD-2-clause License: BSD-2-clause

6
opam
View file

@ -12,7 +12,11 @@ install: [make "install"]
remove: [ remove: [
["ocamlfind" "remove" "sequence"] ["ocamlfind" "remove" "sequence"]
] ]
depends: ["ocamlfind" "base-bytes"] depends: [
"ocamlfind"
"base-bytes"
"ocamlbuild" {build}
]
tags: [ "sequence" "iterator" "iter" "fold" ] tags: [ "sequence" "iterator" "iter" "fold" ]
homepage: "https://github.com/c-cube/sequence/" homepage: "https://github.com/c-cube/sequence/"
depopts: ["delimcc" "base-bigarray"] depopts: ["delimcc" "base-bigarray"]

View file

@ -1,29 +1,7 @@
(*
Copyright (c) 2013, Simon Cruanes
All rights reserved.
Redistribution and use in source and binary forms, with or without (* This file is free software, part of sequence. See file "license" for more details. *)
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this (** {1 Simple and Efficient Iterators} *)
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.} *)
(** Sequence abstract iterator type *) (** Sequence abstract iterator type *)
type 'a t = ('a -> unit) -> unit type 'a t = ('a -> unit) -> unit
@ -31,7 +9,7 @@ type 'a t = ('a -> unit) -> unit
type 'a sequence = 'a t type 'a sequence = 'a t
type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit 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 *) (** Build a sequence from a iter function *)
let from_iter f = f let from_iter f = f
@ -69,8 +47,8 @@ let iteri f seq =
let r = ref 0 in let r = ref 0 in
seq seq
(fun x -> (fun x ->
f !r x; f !r x;
incr r) incr r)
let fold f init seq = let fold f init seq =
let r = ref init in let r = ref init in
@ -82,8 +60,8 @@ let foldi f init seq =
let r = ref init in let r = ref init in
seq seq
(fun elt -> (fun elt ->
r := f !r !i elt; r := f !r !i elt;
incr i); incr i);
!r !r
let map f seq k = seq (fun x -> k (f x)) 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 seq (fun x -> match f x with
| None -> () | None -> ()
| Some y -> k y | Some y -> k y
) )
let filter_map = fmap let filter_map = fmap
@ -130,22 +108,20 @@ module MList = struct
let prev, cur = ref start, ref Nil in let prev, cur = ref start, ref Nil in
seq seq
(fun x -> (fun x ->
k x; (* callback *) k x; (* callback *)
match !cur with match !cur with
| Nil -> | Nil ->
let n = !chunk_size in let n = !chunk_size in
if n < 4096 then chunk_size := 2 * !chunk_size; if n < 4096 then chunk_size := 2 * !chunk_size;
cur := Cons (Array.make n x, ref 1, ref Nil) cur := Cons (Array.make n x, ref 1, ref Nil)
| Cons (a,n,next) -> | Cons (a,n,next) ->
assert (!n < Array.length a); assert (!n < Array.length a);
a.(!n) <- x; a.(!n) <- x;
incr n; incr n;
if !n = Array.length a then begin if !n = Array.length a then (
!prev := !cur; !prev := !cur;
prev := next; prev := next;
cur := Nil cur := Nil));
end
);
!prev := !cur; !prev := !cur;
!start !start
@ -155,13 +131,13 @@ module MList = struct
let rec iter f l = match l with let rec iter f l = match l with
| Nil -> () | Nil -> ()
| Cons (a, n, tl) -> | Cons (a, n, tl) ->
for i=0 to !n - 1 do f a.(i) done; for i=0 to !n - 1 do f a.(i) done;
iter f !tl iter f !tl
let iteri f l = let iteri f l =
let rec iteri i f l = match l with let rec iteri i f l = match l with
| Nil -> () | Nil -> ()
| Cons (a, n, tl) -> | Cons (a, n, tl) ->
for j=0 to !n - 1 do f (i+j) a.(j) done; for j=0 to !n - 1 do f (i+j) a.(j) done;
iteri (i+ !n) f !tl iteri (i+ !n) f !tl
in iteri 0 f l in iteri 0 f l
@ -169,8 +145,8 @@ module MList = struct
let rec iter_rev f l = match l with let rec iter_rev f l = match l with
| Nil -> () | Nil -> ()
| Cons (a, n, tl) -> | Cons (a, n, tl) ->
iter_rev f !tl; iter_rev f !tl;
for i = !n-1 downto 0 do f a.(i) done for i = !n-1 downto 0 do f a.(i) done
let length l = let length l =
let rec len acc l = match l with let rec len acc l = match l with
@ -192,13 +168,13 @@ module MList = struct
let rec get_next _ = match !cur with let rec get_next _ = match !cur with
| Nil -> None | Nil -> None
| Cons (_, n, tl) when !i = !n -> | Cons (_, n, tl) when !i = !n ->
cur := !tl; cur := !tl;
i := 0; i := 0;
get_next arg get_next arg
| Cons (a, _, _) -> | Cons (a, _, _) ->
let x = a.(!i) in let x = a.(!i) in
incr i; incr i;
Some x Some x
in get_next in get_next
let to_gen l = _to_next () l let to_gen l = _to_next () l
@ -228,9 +204,9 @@ let persistent_lazy (seq:'a t) =
match !r with match !r with
| LazyCached seq' -> seq' k | LazyCached seq' -> seq' k
| LazySuspend -> | LazySuspend ->
(* here if this traversal is interruted, no caching occurs *) (* here if this traversal is interruted, no caching occurs *)
let seq' = MList.of_seq_with seq k in let seq' = MList.of_seq_with seq k in
r := LazyCached (MList.to_seq seq') r := LazyCached (MList.to_seq seq')
let sort ?(cmp=Pervasives.compare) seq = let sort ?(cmp=Pervasives.compare) seq =
(* use an intermediate list, then sort the list *) (* use an intermediate list, then sort the list *)
@ -238,63 +214,76 @@ let sort ?(cmp=Pervasives.compare) seq =
let l = List.fast_sort cmp l in let l = List.fast_sort cmp l in
fun k -> List.iter k l 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 let cur = ref [] in
seq (fun x -> seq (fun x ->
match !cur with match !cur with
| [] -> cur := [x] | [] -> cur := [x]
| (y::_) as l when eq x y -> | (y::_) as l when eq x y ->
cur := x::l (* [x] belongs to the group *) cur := x::l (* [x] belongs to the group *)
| (_::_) as l -> | (_::_) as l ->
k l; (* yield group, and start another one *) k l; (* yield group, and start another one *)
cur := [x]); cur := [x]);
(* last list *) (* last list *)
if !cur <> [] then k !cur if !cur <> [] then k !cur
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 uniq ?(eq=fun x y -> x = y) seq k =
let has_prev = ref false let has_prev = ref false
and prev = ref (Obj.magic 0) in (* avoid option type, costly *) and prev = ref (Obj.magic 0) in (* avoid option type, costly *)
seq (fun x -> seq
if !has_prev && eq !prev x (fun x ->
if !has_prev && eq !prev x
then () (* duplicate *) then () (* duplicate *)
else begin else (
has_prev := true; has_prev := true;
prev := x; prev := x;
k x k x
end) ))
let sort_uniq (type elt) ?(cmp=Pervasives.compare) seq = let sort_uniq (type elt) ?(cmp=Pervasives.compare) seq =
let module S = Set.Make(struct let module S = Set.Make(struct
type t = elt type t = elt
let compare = cmp let compare = cmp
end) in end) in
let set = fold (fun acc x -> S.add x acc) S.empty seq in let set = fold (fun acc x -> S.add x acc) S.empty seq in
fun k -> S.iter k set fun k -> S.iter k set
let product outer inner k = let product outer inner k =
outer (fun x -> outer (fun x -> inner (fun y -> k (x,y)))
inner (fun y -> k (x,y))
)
let product2 outer inner k = let product2 outer inner k =
outer (fun x -> outer (fun x -> inner (fun y -> k x y))
inner (fun y -> k x y)
)
let join ~join_row s1 s2 k = let join ~join_row s1 s2 k =
s1 (fun a -> s1 (fun a ->
s2 (fun b -> s2 (fun b ->
match join_row a b with match join_row a b with
| None -> () | None -> ()
| Some c -> k c | Some c -> k c))
)
) (* yield the combination of [a] and [b] *)
let rec unfoldr f b k = match f b with let rec unfoldr f b k = match f b with
| None -> () | None -> ()
| Some (x, b') -> | Some (x, b') ->
k x; k x;
unfoldr f b' k unfoldr f b' k
let scan f acc seq k = let scan f acc seq k =
k acc; k acc;
@ -303,16 +292,18 @@ let scan f acc seq k =
let max ?(lt=fun x y -> x < y) seq = let max ?(lt=fun x y -> x < y) seq =
let ret = ref None in let ret = ref None in
seq (fun x -> match !ret with seq
| None -> ret := Some x (fun x -> match !ret with
| Some y -> if lt y x then ret := Some x); | None -> ret := Some x
| Some y -> if lt y x then ret := Some x);
!ret !ret
let min ?(lt=fun x y -> x < y) seq = let min ?(lt=fun x y -> x < y) seq =
let ret = ref None in let ret = ref None in
seq (fun x -> match !ret with seq
| None -> ret := Some x (fun x -> match !ret with
| Some y -> if lt x y then ret := Some x); | None -> ret := Some x
| Some y -> if lt x y then ret := Some x);
!ret !ret
exception ExitHead exception ExitHead
@ -333,11 +324,11 @@ exception ExitTake
let take n seq k = let take n seq k =
let count = ref 0 in let count = ref 0 in
try try
seq (fun x -> seq
if !count = n then raise ExitTake; (fun x ->
incr count; if !count = n then raise ExitTake;
k x; incr count;
) k x)
with ExitTake -> () with ExitTake -> ()
exception ExitTakeWhile exception ExitTakeWhile
@ -352,11 +343,11 @@ exception ExitFoldWhile
let fold_while f s seq = let fold_while f s seq =
let state = ref s in let state = ref s in
let consume x = let consume x =
let acc, cont = f (!state) x in let acc, cont = f (!state) x in
state := acc; state := acc;
match cont with match cont with
| `Stop -> raise ExitFoldWhile | `Stop -> raise ExitFoldWhile
| `Continue -> () | `Continue -> ()
in in
try try
seq consume; !state seq consume; !state
@ -368,10 +359,11 @@ let drop n seq k =
let drop_while p seq k = let drop_while p seq k =
let drop = ref true in let drop = ref true in
seq (fun x -> seq
if !drop (fun x ->
then if p x then () else (drop := false; k x) if !drop
else k x) then if p x then () else (drop := false; k x)
else k x)
let rev seq = let rev seq =
let l = MList.of_seq seq in let l = MList.of_seq seq in
@ -400,12 +392,13 @@ exception ExitFind
let find f seq = let find f seq =
let r = ref None in let r = ref None in
begin try begin
seq (fun x -> match f x with try
| None -> () seq
| Some _ as res -> r := res; raise ExitFind (fun x -> match f x with
); | None -> ()
with ExitFind -> () | Some _ as res -> r := res; raise ExitFind);
with ExitFind -> ()
end; end;
!r !r
@ -474,17 +467,14 @@ let to_array seq =
let l = MList.of_seq seq in let l = MList.of_seq seq in
let n = MList.length l in let n = MList.length l in
if n = 0 if n = 0
then [||] then [||]
else begin else (
let a = Array.make n (MList.get l 0) in let a = Array.make n (MList.get l 0) in
MList.iteri (fun i x -> a.(i) <- x) l; MList.iteri (fun i x -> a.(i) <- x) l;
a a
end )
let of_array a k = let of_array a k = Array.iter k a
for i = 0 to Array.length a - 1 do
k (Array.unsafe_get a i)
done
let of_array_i a k = let of_array_i a k =
for i = 0 to Array.length a - 1 do for i = 0 to Array.length a - 1 do
@ -565,8 +555,7 @@ let of_in_channel ic =
while true do while true do
let c = input_char ic in k c let c = input_char ic in k c
done done
with End_of_file -> () with End_of_file -> ())
)
let to_buffer seq buf = let to_buffer seq buf =
seq (fun c -> Buffer.add_char buf c) seq (fun c -> Buffer.add_char buf c)
@ -578,6 +567,8 @@ let int_range ~start ~stop k =
let int_range_dec ~start ~stop k = let int_range_dec ~start ~stop k =
for i = start downto stop do k i done 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 of_set (type s) (type v) m set =
let module S = (val m : Set.S with type t = s and type elt = v) in let module S = (val m : Set.S with type t = s and type elt = v) in
fun k -> S.iter k set fun k -> S.iter k set
@ -724,19 +715,19 @@ let pp_seq ?(sep=", ") pp_elt formatter seq =
let first = ref true in let first = ref true in
seq seq
(fun x -> (fun x ->
(if !first then first := false (if !first then first := false
else begin else (
Format.pp_print_string formatter sep; Format.pp_print_string formatter sep;
Format.pp_print_cut formatter (); Format.pp_print_cut formatter ();
end); ));
pp_elt formatter x) pp_elt formatter x)
let pp_buf ?(sep=", ") pp_elt buf seq = let pp_buf ?(sep=", ") pp_elt buf seq =
let first = ref true in let first = ref true in
seq seq
(fun x -> (fun x ->
if !first then first := false else Buffer.add_string buf sep; if !first then first := false else Buffer.add_string buf sep;
pp_elt buf x) pp_elt buf x)
let to_string ?sep pp_elt seq = let to_string ?sep pp_elt seq =
let buf = Buffer.create 25 in let buf = Buffer.create 25 in
@ -774,7 +765,7 @@ module IO = struct
if n' = 0 then stop := true else n := !n + n'; if n' = 0 then stop := true else n := !n + n';
done; done;
if !n > 0 if !n > 0
then k (Bytes.sub_string buf 0 !n) then k (Bytes.sub_string buf 0 !n)
done; done;
close_in ic close_in ic
with e -> with e ->

View file

@ -1,27 +1,5 @@
(*
copyright (c) 2013, simon cruanes
all rights reserved.
redistribution and use in source and binary forms, with or without (* This file is free software, part of sequence. See file "license" for more details. *)
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.
*)
(** {1 Simple and Efficient Iterators} *) (** {1 Simple and Efficient Iterators} *)
@ -53,240 +31,252 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
of this memory structure, cheaply and repeatably. *) of this memory structure, cheaply and repeatably. *)
type +'a t = ('a -> unit) -> unit type +'a t = ('a -> unit) -> unit
(** A sequence of values of type ['a]. If you give it a function ['a -> 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. *) it will be applied to every element of the sequence successively. *)
type +'a sequence = 'a t type +'a sequence = 'a t
type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit 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} *) (** {2 Build a sequence} *)
val from_iter : (('a -> unit) -> unit) -> 'a t 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 val from_fun : (unit -> 'a option) -> 'a t
(** Call the function repeatedly until it returns None. This (** Call the function repeatedly until it returns None. This
sequence is transient, use {!persistent} if needed! *) sequence is transient, use {!persistent} if needed! *)
val empty : 'a t val empty : 'a t
(** Empty sequence. It contains no element. *) (** Empty sequence. It contains no element. *)
val singleton : 'a -> 'a t val singleton : 'a -> 'a t
(** Singleton sequence, with exactly one element. *) (** Singleton sequence, with exactly one element. *)
val doubleton : 'a -> 'a -> 'a t val doubleton : 'a -> 'a -> 'a t
(** Sequence with exactly two elements *) (** Sequence with exactly two elements *)
val cons : 'a -> 'a t -> 'a t val cons : 'a -> 'a t -> 'a t
(** [cons x l] yields [x], then yields from [l]. (** [cons x l] yields [x], then yields from [l].
Same as [append (singleton x) l] *) Same as [append (singleton x) l] *)
val snoc : 'a t -> 'a -> 'a t 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 val return : 'a -> 'a t
(** Synonym to {!singleton} *) (** Synonym to {!singleton} *)
val pure : 'a -> 'a t val pure : 'a -> 'a t
(** Synonym to {!singleton} *) (** Synonym to {!singleton} *)
val repeat : 'a -> 'a t val repeat : 'a -> 'a t
(** Infinite sequence of the same element. You may want to look (** Infinite sequence of the same element. You may want to look
at {!take} and the likes if you iterate on it. *) at {!take} and the likes if you iterate on it. *)
val iterate : ('a -> 'a) -> 'a -> 'a t 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 val forever : (unit -> 'b) -> 'b t
(** Sequence that calls the given function to produce elements. (** Sequence that calls the given function to produce elements.
The sequence may be transient (depending on the function), and definitely The sequence may be transient (depending on the function), and definitely
is infinite. You may want to use {!take} and {!persistent}. *) is infinite. You may want to use {!take} and {!persistent}. *)
val cycle : 'a t -> 'a t val cycle : 'a t -> 'a t
(** Cycle forever through the given sequence. Assume the given sequence can (** Cycle forever through the given sequence. Assume the given sequence can
be traversed any amount of times (not transient). This yields an be traversed any amount of times (not transient). This yields an
infinite sequence, you should use something like {!take} not to loop infinite sequence, you should use something like {!take} not to loop
forever. *) forever. *)
(** {2 Consume a sequence} *) (** {2 Consume a sequence} *)
val iter : ('a -> unit) -> 'a t -> unit val iter : ('a -> unit) -> 'a t -> unit
(** Consume the sequence, passing all its arguments to the function. (** Consume the sequence, passing all its arguments to the function.
Basically [iter f seq] is just [seq f]. *) Basically [iter f seq] is just [seq f]. *)
val iteri : (int -> 'a -> unit) -> 'a t -> unit 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 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 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 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 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 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 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 val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool
(** Is the value a member of the sequence? (** Is the value a member of the sequence?
@param eq the equality predicate to use (default [(=)]) @param eq the equality predicate to use (default [(=)])
@since 0.5 *) @since 0.5 *)
val find : ('a -> 'b option) -> 'a t -> 'b option val find : ('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]
@since 0.5 *) @since 0.5 *)
val length : 'a t -> int 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 val is_empty : 'a t -> bool
(** Is the sequence empty? Forces the sequence. *) (** Is the sequence empty? Forces the sequence. *)
(** {2 Transform a sequence} *) (** {2 Transform a sequence} *)
val filter : ('a -> bool) -> 'a t -> 'a t 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 val append : 'a t -> 'a t -> 'a t
(** Append two sequences. Iterating on the result is like iterating (** Append two sequences. Iterating on the result is like iterating
on the first, then on the second. *) on the first, then on the second. *)
val concat : 'a t t -> 'a t 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 val flatten : 'a t t -> 'a t
(** Alias for {!concat} *) (** Alias for {!concat} *)
val flatMap : ('a -> 'b t) -> 'a t -> 'b t val flatMap : ('a -> 'b t) -> 'a t -> 'b t
(** Monadic bind. Intuitively, it applies the function to every element of the (** @deprecated use {!flat_map} since NEXT_RELEASE *)
initial sequence, and calls {!concat}. *)
val flat_map : ('a -> 'b t) -> 'a t -> 'b t 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
@since 0.5 *) element of the initial sequence, and calls {!concat}.
@since 0.5 *)
val fmap : ('a -> 'b option) -> 'a t -> 'b t 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 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 *) @since 0.5 *)
val intersperse : 'a -> 'a t -> 'a t 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} *) (** {2 Caching} *)
val persistent : 'a t -> 'a t val persistent : 'a t -> 'a t
(** Iterate on the sequence, storing elements in an efficient internal structure.. (** Iterate on the sequence, storing elements in an efficient internal structure..
The resulting sequence can be iterated on as many times as needed. The resulting sequence can be iterated on as many times as needed.
{b Note}: calling persistent on an already persistent sequence {b Note}: calling persistent on an already persistent sequence
will still make a new copy of the sequence! *) will still make a new copy of the sequence! *)
val persistent_lazy : 'a t -> 'a t val persistent_lazy : 'a t -> 'a t
(** Lazy version of {!persistent}. When calling [persistent_lazy s], (** Lazy version of {!persistent}. When calling [persistent_lazy s],
a new sequence [s'] is immediately returned (without actually consuming a new sequence [s'] is immediately returned (without actually consuming
[s]) in constant time; the first time [s'] is iterated on, [s]) in constant time; the first time [s'] is iterated on,
it also consumes [s] and caches its content into a inner data it also consumes [s] and caches its content into a inner data
structure that will back [s'] for future iterations. structure that will back [s'] for future iterations.
{b warning}: on the first traversal of [s'], if the traversal {b warning}: on the first traversal of [s'], if the traversal
is interrupted prematurely ({!take}, etc.) then [s'] will not be is interrupted prematurely ({!take}, etc.) then [s'] will not be
memorized, and the next call to [s'] will traverse [s] again. *) memorized, and the next call to [s'] will traverse [s] again. *)
(** {2 Misc} *) (** {2 Misc} *)
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time.
It iterates on elements of the argument sequence immediately, It iterates on elements of the argument sequence immediately,
before it sorts them. *) before it sorts them. *)
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t 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 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 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 val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
(** Remove consecutive duplicate elements. Basically this is (** Remove consecutive duplicate elements. Basically this is
like [fun seq -> map List.hd (group seq)]. *) like [fun seq -> map List.hd (group seq)]. *)
val product : 'a t -> 'b t -> ('a * 'b) t val product : 'a t -> 'b t -> ('a * 'b) t
(** Cartesian product of the sequences. When calling [product a b], (** Cartesian product of the sequences. When calling [product a b],
the caller {b MUST} ensure that [b] can be traversed as many times the caller {b MUST} ensure that [b] can be traversed as many times
as required (several times), possibly by calling {!persistent} on it as required (several times), possibly by calling {!persistent} on it
beforehand. *) beforehand. *)
val product2 : 'a t -> 'b t -> ('a, 'b) t2 val product2 : 'a t -> 'b t -> ('a, 'b) t2
(** Binary version of {!product}. Same requirements. (** Binary version of {!product}. Same requirements.
@since 0.5 *) @since 0.5 *)
val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t 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 (** [join ~join_row a b] combines every element of [a] with every
element of [b] using [join_row]. If [join_row] returns None, then element of [b] using [join_row]. If [join_row] returns None, then
the two elements do not combine. Assume that [b] allows for multiple the two elements do not combine. Assume that [b] allows for multiple
iterations. *) iterations. *)
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
(** [unfoldr f b] will apply [f] to [b]. If it (** [unfoldr f b] will apply [f] to [b]. If it
yields [Some (x,b')] then [x] is returned yields [Some (x,b')] then [x] is returned
and unfoldr recurses with [b']. *) and unfoldr recurses with [b']. *)
val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t 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 val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
(** Max element of the sequence, using the given comparison function. (** Max element of the sequence, using the given comparison function.
@return None if the sequence is empty, Some [m] where [m] is the maximal @return None if the sequence is empty, Some [m] where [m] is the maximal
element otherwise *) element otherwise *)
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
(** Min element of the sequence, using the given comparison function. (** Min element of the sequence, using the given comparison function.
see {!max} for more details. *) see {!max} for more details. *)
val head : 'a t -> 'a option val head : 'a t -> 'a option
(** First element, if any, otherwise [None] (** First element, if any, otherwise [None]
@since 0.5.1 *) @since 0.5.1 *)
val head_exn : 'a t -> 'a val head_exn : 'a t -> 'a
(** First element, if any, fails (** First element, if any, fails
@raise Invalid_argument if the sequence is empty @raise Invalid_argument if the sequence is empty
@since 0.5.1 *) @since 0.5.1 *)
val take : int -> 'a t -> 'a t val take : int -> 'a t -> 'a t
(** Take at most [n] elements from the sequence. Works on infinite (** Take at most [n] elements from the sequence. Works on infinite
sequences. *) sequences. *)
val take_while : ('a -> bool) -> 'a t -> 'a t val take_while : ('a -> bool) -> 'a t -> 'a t
(** Take elements while they satisfy the predicate, then stops iterating. (** Take elements while they satisfy the predicate, then stops iterating.
Will work on an infinite sequence [s] if the predicate is false for at Will work on an infinite sequence [s] if the predicate is false for at
least one element of [s]. *) least one element of [s]. *)
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
(** Folds over elements of the sequence, stopping early if the accumulator (** Folds over elements of the sequence, stopping early if the accumulator
returns [('a, `Stop)] returns [('a, `Stop)]
@since 0.5.5 *) @since 0.5.5 *)
val drop : int -> 'a t -> 'a t 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 val drop_while : ('a -> bool) -> 'a t -> 'a t
(** Predicate version of {!drop} *) (** Predicate version of {!drop} *)
val rev : 'a t -> 'a t val rev : 'a t -> 'a t
(** Reverse the sequence. O(n) memory and time, needs the (** Reverse the sequence. O(n) memory and time, needs the
sequence to be finite. The result is persistent and does sequence to be finite. The result is persistent and does
not depend on the input being repeatable. *) not depend on the input being repeatable. *)
(** {2 Binary sequences} *) (** {2 Binary sequences} *)
@ -301,7 +291,7 @@ val zip : ('a, 'b) t2 -> ('a * 'b) t
val unzip : ('a * 'b) t -> ('a, 'b) t2 val unzip : ('a * 'b) t -> ('a, 'b) t2
val zip_i : 'a t -> (int, 'a) 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 val fold2 : ('c -> 'a -> 'b -> 'c) -> 'c -> ('a, 'b) t2 -> 'c
@ -310,17 +300,17 @@ val iter2 : ('a -> 'b -> unit) -> ('a, 'b) t2 -> unit
val map2 : ('a -> 'b -> 'c) -> ('a, 'b) t2 -> 'c t 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 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} *) (** {2 Basic data structures converters} *)
val to_list : 'a t -> 'a list val to_list : 'a t -> 'a list
(** Convert the sequence into a list. Preserves order of elements. (** Convert the sequence into a list. Preserves order of elements.
This function is tail-recursive, but consumes 2*n memory. This function is tail-recursive, but consumes 2*n memory.
If order doesn't matter to you, consider {!to_rev_list}. *) If order doesn't matter to you, consider {!to_rev_list}. *)
val to_rev_list : 'a t -> 'a 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 val of_list : 'a list -> 'a t
@ -330,65 +320,65 @@ val on_list : ('a t -> 'b t) -> 'a list -> 'b list
*) *)
val to_opt : 'a t -> 'a option val to_opt : 'a t -> 'a option
(** Alias to {!head} (** Alias to {!head}
@since 0.5.1 *) @since 0.5.1 *)
val to_array : 'a t -> 'a array val to_array : 'a t -> 'a array
(** Convert to an array. Currently not very efficient because (** Convert to an array. Currently not very efficient because
an intermediate list is used. *) an intermediate list is used. *)
val of_array : 'a array -> 'a t val of_array : 'a array -> 'a t
val of_array_i : 'a array -> (int * '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 of_array2 : 'a array -> (int, 'a) t2
val array_slice : 'a array -> int -> int -> 'a t val array_slice : 'a array -> int -> int -> 'a t
(** [array_slice a i j] Sequence of elements whose indexes range (** [array_slice a i j] Sequence of elements whose indexes range
from [i] to [j] *) from [i] to [j] *)
val of_opt : 'a option -> 'a t val of_opt : 'a option -> 'a t
(** Iterate on 0 or 1 values. (** Iterate on 0 or 1 values.
@since 0.5.1 *) @since 0.5.1 *)
val of_stream : 'a Stream.t -> 'a t 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 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 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 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 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 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 val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
(** Add elements of the sequence to the hashtable, with (** Add elements of the sequence to the hashtable, with
Hashtbl.add *) Hashtbl.add *)
val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
(** Add elements of the sequence to the hashtable, with (** Add elements of the sequence to the hashtable, with
Hashtbl.replace (erases conflicting bindings) *) Hashtbl.replace (erases conflicting bindings) *)
val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t 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 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 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 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_keys : ('a, 'b) Hashtbl.t -> 'a t
val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b t val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b t
@ -397,51 +387,55 @@ val of_str : string -> char t
val to_str : char t -> string val to_str : char t -> string
val concat_str : string t -> string val concat_str : string t -> string
(** Concatenate strings together, eagerly. (** Concatenate strings together, eagerly.
Also see {!intersperse} to add a separator. Also see {!intersperse} to add a separator.
@since 0.5 *) @since 0.5 *)
exception OneShotSequence exception OneShotSequence
(** Raised when the user tries to iterate several times on (** Raised when the user tries to iterate several times on
a transient iterator *) a transient iterator *)
val of_in_channel : in_channel -> char t val of_in_channel : in_channel -> char t
(** Iterates on characters of the input (can block when one (** Iterates on characters of the input (can block when one
iterates over the sequence). If you need to iterate iterates over the sequence). If you need to iterate
several times on this sequence, use {!persistent}. several times on this sequence, use {!persistent}.
@raise OneShotSequence when used more than once. *) @raise OneShotSequence when used more than once. *)
val to_buffer : char t -> Buffer.t -> unit 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 val int_range : start:int -> stop:int -> int t
(** Iterator on integers in [start...stop] by steps 1. Also see (** Iterator on integers in [start...stop] by steps 1. Also see
{!(--)} for an infix version. *) {!(--)} for an infix version. *)
val int_range_dec : start:int -> stop:int -> int t val int_range_dec : start:int -> stop:int -> int t
(** Iterator on decreasing integers in [stop...start] by steps -1. (** Iterator on decreasing integers in [stop...start] by steps -1.
See {!(--^)} for an infix version *) 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 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 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 gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist] type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
val of_gen : 'a gen -> 'a t 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 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 val of_klist : 'a klist -> 'a t
(** Iterate on the lazy list *) (** Iterate on the lazy list *)
val to_klist : 'a t -> 'a klist 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} *) (** {2 Functorial conversions between sets and sequences} *)
@ -484,48 +478,48 @@ end
(** {2 Infinite sequences of random values} *) (** {2 Infinite sequences of random values} *)
val random_int : int -> int t val random_int : int -> int t
(** Infinite sequence of random integers between 0 and (** Infinite sequence of random integers between 0 and
the given higher bound (see Random.int) *) the given higher bound (see Random.int) *)
val random_bool : bool t 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_float : float -> float t
val random_array : 'a array -> 'a 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 val random_list : 'a list -> 'a t
(** Infinite sequence of random elements of the list. Basically the (** Infinite sequence of random elements of the list. Basically the
same as {!random_array}. *) same as {!random_array}. *)
(** {2 Infix functions} *) (** {2 Infix functions} *)
module Infix : sig module Infix : sig
val (--) : int -> int -> int t val (--) : int -> int -> int t
(** [a -- b] is the range of integers from [a] to [b], both included, (** [a -- b] is the range of integers from [a] to [b], both included,
in increasing order. It will therefore be empty if [a > b]. *) in increasing order. It will therefore be empty if [a > b]. *)
val (--^) : int -> int -> int t val (--^) : int -> int -> int t
(** [a --^ b] is the range of integers from [b] to [a], both included, (** [a --^ b] is the range of integers from [b] to [a], both included,
in decreasing order (starts from [a]). in decreasing order (starts from [a]).
It will therefore be empty if [a < b]. *) It will therefore be empty if [a < b]. *)
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
(** Monadic bind (infix version of {!flat_map} (** Monadic bind (infix version of {!flat_map}
@since 0.5 *) @since 0.5 *)
val (>|=) : 'a t -> ('a -> 'b) -> 'b t val (>|=) : 'a t -> ('a -> 'b) -> 'b t
(** Infix version of {!map} (** Infix version of {!map}
@since 0.5 *) @since 0.5 *)
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
(** Applicative operator (product+application) (** Applicative operator (product+application)
@since 0.5 *) @since 0.5 *)
val (<+>) : 'a t -> 'a t -> 'a t val (<+>) : 'a t -> 'a t -> 'a t
(** Concatenation of sequences (** Concatenation of sequences
@since 0.5 *) @since 0.5 *)
end end
include module type of Infix include module type of Infix
@ -533,46 +527,46 @@ include module type of Infix
(** {2 Pretty printing of sequences} *) (** {2 Pretty printing of sequences} *)
val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) -> val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) ->
Format.formatter -> 'a t -> unit Format.formatter -> 'a t -> unit
(** Pretty print a sequence of ['a], using the given pretty printer (** Pretty print a sequence of ['a], using the given pretty printer
to print each elements. An optional separator string can be provided. *) to print each elements. An optional separator string can be provided. *)
val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) -> val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) ->
Buffer.t -> 'a t -> unit Buffer.t -> 'a t -> unit
(** Print into a buffer *) (** Print into a buffer *)
val to_string : ?sep:string -> ('a -> string) -> 'a t -> string val to_string : ?sep:string -> ('a -> string) -> 'a t -> string
(** Print into a string *) (** Print into a string *)
(** {2 Basic IO} (** {2 Basic IO}
Very basic interface to manipulate files as sequence of chunks/lines. The Very basic interface to manipulate files as sequence of chunks/lines. The
sequences take care of opening and closing files properly; every time sequences take care of opening and closing files properly; every time
one iterates over a sequence, the file is opened/closed again. 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 module IO : sig
val lines_of : ?mode:int -> ?flags:open_flag list -> 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 (** [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 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 from [End_of_file] (which is caught). The file is {b always} properly
@ -583,28 +577,28 @@ module IO : sig
@param flags default: [[Open_rdonly]] *) @param flags default: [[Open_rdonly]] *)
val chunks_of : ?mode:int -> ?flags:open_flag list -> ?size:int -> 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 (** Read chunks of the given [size] from the file. The last chunk might be
smaller. Behaves like {!lines_of} regarding errors and options. smaller. Behaves like {!lines_of} regarding errors and options.
Every time the sequence is iterated on, the file is opened again, so Every time the sequence is iterated on, the file is opened again, so
different iterations might return different results *) different iterations might return different results *)
val write_to : ?mode:int -> ?flags:open_flag list -> 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 (** [write_to filename seq] writes all strings from [seq] into the given
file. It takes care of opening and closing the file. file. It takes care of opening and closing the file.
@param mode default [0o644] @param mode default [0o644]
@param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *) @param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *)
val write_bytes_to : ?mode:int -> ?flags:open_flag list -> val write_bytes_to : ?mode:int -> ?flags:open_flag list ->
string -> Bytes.t t -> unit string -> Bytes.t t -> unit
(** @since 0.5.4 *) (** @since 0.5.4 *)
val write_lines : ?mode:int -> ?flags:open_flag list -> 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 *) (** Same as {!write_to}, but intercales ['\n'] between each string *)
val write_bytes_lines : ?mode:int -> ?flags:open_flag list -> val write_bytes_lines : ?mode:int -> ?flags:open_flag list ->
string -> Bytes.t t -> unit string -> Bytes.t t -> unit
(** @since 0.5.4 *) (** @since 0.5.4 *)
end end

View file

@ -1,263 +1,239 @@
(*
copyright (c) 2013, simon cruanes
all rights reserved.
redistribution and use in source and binary forms, with or without (* This file is free software, part of sequence. See file "license" for more details. *)
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.
*)
(** {1 Simple and Efficient Iterators} (** {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 type +'a t = ('a -> unit) -> unit
(** A sequence of values of type ['a]. If you give it a function ['a -> 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. *) it will be applied to every element of the sequence successively. *)
type +'a sequence = 'a t type +'a sequence = 'a t
type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit 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} *) (** {2 Build a sequence} *)
val from_iter : (('a -> unit) -> unit) -> 'a t 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 val from_fun : (unit -> 'a option) -> 'a t
(** Call the function repeatedly until it returns None. This (** Call the function repeatedly until it returns None. This
sequence is transient, use {!persistent} if needed! *) sequence is transient, use {!persistent} if needed! *)
val empty : 'a t val empty : 'a t
(** Empty sequence. It contains no element. *) (** Empty sequence. It contains no element. *)
val singleton : 'a -> 'a t val singleton : 'a -> 'a t
(** Singleton sequence, with exactly one element. *) (** Singleton sequence, with exactly one element. *)
val doubleton : 'a -> 'a -> 'a t val doubleton : 'a -> 'a -> 'a t
(** Sequence with exactly two elements *) (** Sequence with exactly two elements *)
val cons : 'a -> 'a t -> 'a t val cons : 'a -> 'a t -> 'a t
(** [cons x l] yields [x], then yields from [l]. (** [cons x l] yields [x], then yields from [l].
Same as [append (singleton x) l] *) Same as [append (singleton x) l] *)
val snoc : 'a t -> 'a -> 'a t 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 val return : 'a -> 'a t
(** Synonym to {!singleton} *) (** Synonym to {!singleton} *)
val pure : 'a -> 'a t val pure : 'a -> 'a t
(** Synonym to {!singleton} *) (** Synonym to {!singleton} *)
val repeat : 'a -> 'a t val repeat : 'a -> 'a t
(** Infinite sequence of the same element. You may want to look (** Infinite sequence of the same element. You may want to look
at {!take} and the likes if you iterate on it. *) at {!take} and the likes if you iterate on it. *)
val iterate : ('a -> 'a) -> 'a -> 'a t 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 val forever : (unit -> 'b) -> 'b t
(** Sequence that calls the given function to produce elements. (** Sequence that calls the given function to produce elements.
The sequence may be transient (depending on the function), and definitely The sequence may be transient (depending on the function), and definitely
is infinite. You may want to use {!take} and {!persistent}. *) is infinite. You may want to use {!take} and {!persistent}. *)
val cycle : 'a t -> 'a t val cycle : 'a t -> 'a t
(** Cycle forever through the given sequence. Assume the given sequence can (** Cycle forever through the given sequence. Assume the given sequence can
be traversed any amount of times (not transient). This yields an be traversed any amount of times (not transient). This yields an
infinite sequence, you should use something like {!take} not to loop infinite sequence, you should use something like {!take} not to loop
forever. *) forever. *)
(** {2 Consume a sequence} *) (** {2 Consume a sequence} *)
val iter : f:('a -> unit) -> 'a t -> unit val iter : f:('a -> unit) -> 'a t -> unit
(** Consume the sequence, passing all its arguments to the function. (** Consume the sequence, passing all its arguments to the function.
Basically [iter f seq] is just [seq f]. *) Basically [iter f seq] is just [seq f]. *)
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit 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 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 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 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 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 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 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 val mem : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> bool
(** Is the value a member of the sequence? (** Is the value a member of the sequence?
@param eq the equality predicate to use (default [(=)]) *) @param eq the equality predicate to use (default [(=)]) *)
val find : f:('a -> 'b option) -> 'a t -> 'b option 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 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 val is_empty : 'a t -> bool
(** Is the sequence empty? Forces the sequence. *) (** Is the sequence empty? Forces the sequence. *)
(** {2 Transform a sequence} *) (** {2 Transform a sequence} *)
val filter : f:('a -> bool) -> 'a t -> 'a t 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 val append : 'a t -> 'a t -> 'a t
(** Append two sequences. Iterating on the result is like iterating (** Append two sequences. Iterating on the result is like iterating
on the first, then on the second. *) on the first, then on the second. *)
val concat : 'a t t -> 'a t 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 val flatten : 'a t t -> 'a t
(** Alias for {!concat} *) (** Alias for {!concat} *)
val flatMap : f:('a -> 'b t) -> 'a t -> 'b t val flatMap : f:('a -> 'b t) -> 'a t -> 'b t
(** Monadic bind. Intuitively, it applies the function to every element of the (** @deprecated use {!flat_map} *)
initial sequence, and calls {!concat}.
@deprecated use {!flat_map} *)
val flat_map : f:('a -> 'b t) -> 'a t -> 'b t 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 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 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 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} *) (** {2 Caching} *)
val persistent : 'a t -> 'a t val persistent : 'a t -> 'a t
(** Iterate on the sequence, storing elements in an efficient internal structure.. (** Iterate on the sequence, storing elements in an efficient internal structure..
The resulting sequence can be iterated on as many times as needed. The resulting sequence can be iterated on as many times as needed.
{b Note}: calling persistent on an already persistent sequence {b Note}: calling persistent on an already persistent sequence
will still make a new copy of the sequence! *) will still make a new copy of the sequence! *)
val persistent_lazy : 'a t -> 'a t val persistent_lazy : 'a t -> 'a t
(** Lazy version of {!persistent}. When calling [persistent_lazy s], (** Lazy version of {!persistent}. When calling [persistent_lazy s],
a new sequence [s'] is immediately returned (without actually consuming a new sequence [s'] is immediately returned (without actually consuming
[s]) in constant time; the first time [s'] is iterated on, [s]) in constant time; the first time [s'] is iterated on,
it also consumes [s] and caches its content into a inner data it also consumes [s] and caches its content into a inner data
structure that will back [s'] for future iterations. structure that will back [s'] for future iterations.
{b warning}: on the first traversal of [s'], if the traversal {b warning}: on the first traversal of [s'], if the traversal
is interrupted prematurely ({!take}, etc.) then [s'] will not be is interrupted prematurely ({!take}, etc.) then [s'] will not be
memorized, and the next call to [s'] will traverse [s] again. *) memorized, and the next call to [s'] will traverse [s] again. *)
(** {2 Misc} *) (** {2 Misc} *)
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time.
It iterates on elements of the argument sequence immediately, It iterates on elements of the argument sequence immediately,
before it sorts them. *) before it sorts them. *)
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t 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 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 val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
(** Remove consecutive duplicate elements. Basically this is (** Remove consecutive duplicate elements. Basically this is
like [fun seq -> map List.hd (group seq)]. *) like [fun seq -> map List.hd (group seq)]. *)
val product : 'a t -> 'b t -> ('a * 'b) t val product : 'a t -> 'b t -> ('a * 'b) t
(** Cartesian product of the sequences. When calling [product a b], (** Cartesian product of the sequences. When calling [product a b],
the caller {b MUST} ensure that [b] can be traversed as many times the caller {b MUST} ensure that [b] can be traversed as many times
as required (several times), possibly by calling {!persistent} on it as required (several times), possibly by calling {!persistent} on it
beforehand. *) beforehand. *)
val product2 : 'a t -> 'b t -> ('a, 'b) t2 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 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 (** [join ~join_row a b] combines every element of [a] with every
element of [b] using [join_row]. If [join_row] returns None, then element of [b] using [join_row]. If [join_row] returns None, then
the two elements do not combine. Assume that [b] allows for multiple the two elements do not combine. Assume that [b] allows for multiple
iterations. *) iterations. *)
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
(** [unfoldr f b] will apply [f] to [b]. If it (** [unfoldr f b] will apply [f] to [b]. If it
yields [Some (x,b')] then [x] is returned yields [Some (x,b')] then [x] is returned
and unfoldr recurses with [b']. *) and unfoldr recurses with [b']. *)
val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t 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 val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
(** Max element of the sequence, using the given comparison function. (** Max element of the sequence, using the given comparison function.
@return None if the sequence is empty, Some [m] where [m] is the maximal @return None if the sequence is empty, Some [m] where [m] is the maximal
element otherwise *) element otherwise *)
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
(** Min element of the sequence, using the given comparison function. (** Min element of the sequence, using the given comparison function.
see {!max} for more details. *) see {!max} for more details. *)
val head : 'a t -> 'a option val head : 'a t -> 'a option
(** First element, if any, otherwise [None] *) (** First element, if any, otherwise [None] *)
val head_exn : 'a t -> 'a val head_exn : 'a t -> 'a
(** First element, if any, fails (** First element, if any, fails
@raise Invalid_argument if the sequence is empty *) @raise Invalid_argument if the sequence is empty *)
val take : int -> 'a t -> 'a t val take : int -> 'a t -> 'a t
(** Take at most [n] elements from the sequence. Works on infinite (** Take at most [n] elements from the sequence. Works on infinite
sequences. *) sequences. *)
val take_while : f:('a -> bool) -> 'a t -> 'a t val take_while : f:('a -> bool) -> 'a t -> 'a t
(** Take elements while they satisfy the predicate, then stops iterating. (** Take elements while they satisfy the predicate, then stops iterating.
Will work on an infinite sequence [s] if the predicate is false for at Will work on an infinite sequence [s] if the predicate is false for at
least one element of [s]. *) least one element of [s]. *)
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a 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 (** Folds over elements of the sequence, stopping early if the accumulator
returns [('a, `Stop)] *) returns [('a, `Stop)] *)
val drop : int -> 'a t -> 'a t 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 val drop_while : f:('a -> bool) -> 'a t -> 'a t
(** Predicate version of {!drop} *) (** Predicate version of {!drop} *)
val rev : 'a t -> 'a t val rev : 'a t -> 'a t
(** Reverse the sequence. O(n) memory and time, needs the (** Reverse the sequence. O(n) memory and time, needs the
sequence to be finite. The result is persistent and does sequence to be finite. The result is persistent and does
not depend on the input being repeatable. *) not depend on the input being repeatable. *)
(** {2 Binary sequences} *) (** {2 Binary sequences} *)
@ -272,7 +248,7 @@ val zip : ('a, 'b) t2 -> ('a * 'b) t
val unzip : ('a * 'b) t -> ('a, 'b) t2 val unzip : ('a * 'b) t -> ('a, 'b) t2
val zip_i : 'a t -> (int, 'a) 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 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 : f:('a -> 'b -> 'c) -> ('a, 'b) t2 -> 'c t
val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a, 'b) t2 -> ('c, 'd) t2 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} *) (** {2 Basic data structures converters} *)
val to_list : 'a t -> 'a list val to_list : 'a t -> 'a list
(** Convert the sequence into a list. Preserves order of elements. (** Convert the sequence into a list. Preserves order of elements.
This function is tail-recursive, but consumes 2*n memory. This function is tail-recursive, but consumes 2*n memory.
If order doesn't matter to you, consider {!to_rev_list}. *) If order doesn't matter to you, consider {!to_rev_list}. *)
val to_rev_list : 'a t -> 'a 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 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]. *) (** [on_list f l] is equivalent to [to_list @@ f @@ of_list l]. *)
val to_opt : 'a t -> 'a option val to_opt : 'a t -> 'a option
(** Alias to {!head} *) (** Alias to {!head} *)
val to_array : 'a t -> 'a array val to_array : 'a t -> 'a array
(** Convert to an array. Currently not very efficient because (** Convert to an array. Currently not very efficient because
an intermediate list is used. *) an intermediate list is used. *)
val of_array : 'a array -> 'a t val of_array : 'a array -> 'a t
val of_array_i : 'a array -> (int * '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 of_array2 : 'a array -> (int, 'a) t2
val array_slice : 'a array -> int -> int -> 'a t val array_slice : 'a array -> int -> int -> 'a t
(** [array_slice a i j] Sequence of elements whose indexes range (** [array_slice a i j] Sequence of elements whose indexes range
from [i] to [j] *) from [i] to [j] *)
val of_opt : 'a option -> 'a t 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 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 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 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 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 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 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 val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
(** Add elements of the sequence to the hashtable, with (** Add elements of the sequence to the hashtable, with
Hashtbl.add *) Hashtbl.add *)
val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
(** Add elements of the sequence to the hashtable, with (** Add elements of the sequence to the hashtable, with
Hashtbl.replace (erases conflicting bindings) *) Hashtbl.replace (erases conflicting bindings) *)
val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t 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 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 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 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_keys : ('a, 'b) Hashtbl.t -> 'a t
val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b 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 to_str : char t -> string
val concat_str : string t -> string val concat_str : string t -> string
(** Concatenate strings together, eagerly. (** Concatenate strings together, eagerly.
Also see {!intersperse} to add a separator. *) Also see {!intersperse} to add a separator. *)
exception OneShotSequence exception OneShotSequence
(** Raised when the user tries to iterate several times on (** Raised when the user tries to iterate several times on
a transient iterator *) a transient iterator *)
val of_in_channel : in_channel -> char t val of_in_channel : in_channel -> char t
(** Iterates on characters of the input (can block when one (** Iterates on characters of the input (can block when one
iterates over the sequence). If you need to iterate iterates over the sequence). If you need to iterate
several times on this sequence, use {!persistent}. several times on this sequence, use {!persistent}.
@raise OneShotSequence when used more than once. *) @raise OneShotSequence when used more than once. *)
val to_buffer : char t -> Buffer.t -> unit 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 val int_range : start:int -> stop:int -> int t
(** Iterator on integers in [start...stop] by steps 1. Also see (** Iterator on integers in [start...stop] by steps 1. Also see
{!(--)} for an infix version. *) {!(--)} for an infix version. *)
val int_range_dec : start:int -> stop:int -> int t val int_range_dec : start:int -> stop:int -> int t
(** Iterator on decreasing integers in [stop...start] by steps -1. (** Iterator on decreasing integers in [stop...start] by steps -1.
See {!(--^)} for an infix version *) See {!(--^)} for an infix version *)
val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t 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 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 gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist] type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
val of_gen : 'a gen -> 'a t 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 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 val of_klist : 'a klist -> 'a t
(** Iterate on the lazy list *) (** Iterate on the lazy list *)
val to_klist : 'a t -> 'a klist 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} *) (** {2 Functorial conversions between sets and sequences} *)
@ -450,44 +426,44 @@ end
(** {2 Infinite sequences of random values} *) (** {2 Infinite sequences of random values} *)
val random_int : int -> int t val random_int : int -> int t
(** Infinite sequence of random integers between 0 and (** Infinite sequence of random integers between 0 and
the given higher bound (see Random.int) *) the given higher bound (see Random.int) *)
val random_bool : bool t 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_float : float -> float t
val random_array : 'a array -> 'a 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 val random_list : 'a list -> 'a t
(** Infinite sequence of random elements of the list. Basically the (** Infinite sequence of random elements of the list. Basically the
same as {!random_array}. *) same as {!random_array}. *)
(** {2 Infix functions} *) (** {2 Infix functions} *)
module Infix : sig module Infix : sig
val (--) : int -> int -> int t val (--) : int -> int -> int t
(** [a -- b] is the range of integers from [a] to [b], both included, (** [a -- b] is the range of integers from [a] to [b], both included,
in increasing order. It will therefore be empty if [a > b]. *) in increasing order. It will therefore be empty if [a > b]. *)
val (--^) : int -> int -> int t val (--^) : int -> int -> int t
(** [a --^ b] is the range of integers from [b] to [a], both included, (** [a --^ b] is the range of integers from [b] to [a], both included,
in decreasing order (starts from [a]). in decreasing order (starts from [a]).
It will therefore be empty if [a < b]. *) It will therefore be empty if [a < b]. *)
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t 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 val (>|=) : 'a t -> ('a -> 'b) -> 'b t
(** Infix version of {!map} *) (** Infix version of {!map} *)
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
(** Applicative operator (product+application) *) (** Applicative operator (product+application) *)
val (<+>) : 'a t -> 'a t -> 'a t val (<+>) : 'a t -> 'a t -> 'a t
(** Concatenation of sequences *) (** Concatenation of sequences *)
end end
include module type of Infix include module type of Infix
@ -496,46 +472,46 @@ include module type of Infix
(** {2 Pretty printing of sequences} *) (** {2 Pretty printing of sequences} *)
val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) -> val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) ->
Format.formatter -> 'a t -> unit Format.formatter -> 'a t -> unit
(** Pretty print a sequence of ['a], using the given pretty printer (** Pretty print a sequence of ['a], using the given pretty printer
to print each elements. An optional separator string can be provided. *) to print each elements. An optional separator string can be provided. *)
val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) -> val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) ->
Buffer.t -> 'a t -> unit Buffer.t -> 'a t -> unit
(** Print into a buffer *) (** Print into a buffer *)
val to_string : ?sep:string -> ('a -> string) -> 'a t -> string val to_string : ?sep:string -> ('a -> string) -> 'a t -> string
(** Print into a string *) (** Print into a string *)
(** {2 Basic IO} (** {2 Basic IO}
Very basic interface to manipulate files as sequence of chunks/lines. The Very basic interface to manipulate files as sequence of chunks/lines. The
sequences take care of opening and closing files properly; every time sequences take care of opening and closing files properly; every time
one iterates over a sequence, the file is opened/closed again. 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 module IO : sig
val lines_of : ?mode:int -> ?flags:open_flag list -> 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 (** [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 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 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]] *) @param flags default: [[Open_rdonly]] *)
val chunks_of : ?mode:int -> ?flags:open_flag list -> ?size:int -> 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 (** Read chunks of the given [size] from the file. The last chunk might be
smaller. Behaves like {!lines_of} regarding errors and options. smaller. Behaves like {!lines_of} regarding errors and options.
Every time the sequence is iterated on, the file is opened again, so Every time the sequence is iterated on, the file is opened again, so
different iterations might return different results *) different iterations might return different results *)
val write_to : ?mode:int -> ?flags:open_flag list -> 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 (** [write_to filename seq] writes all strings from [seq] into the given
file. It takes care of opening and closing the file. file. It takes care of opening and closing the file.
@param mode default [0o644] @param mode default [0o644]
@param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *) @param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *)
val write_bytes_to : ?mode:int -> ?flags:open_flag list -> 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 -> 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 *) (** Same as {!write_to}, but intercales ['\n'] between each string *)
val write_bytes_lines : ?mode:int -> ?flags:open_flag list -> val write_bytes_lines : ?mode:int -> ?flags:open_flag list ->
string -> Bytes.t t -> unit string -> Bytes.t t -> unit
end end

View file

@ -1,7 +1,7 @@
(* setup.ml generated for the first time by OASIS v0.4.4 *) (* setup.ml generated for the first time by OASIS v0.4.4 *)
(* OASIS_START *) (* OASIS_START *)
(* DO NOT EDIT (digest: 333f749d9a0c9bcd48d939db40a13c4b) *) (* DO NOT EDIT (digest: ba3f6d5b3b5e6f77424dfec99217b2f6) *)
(* (*
Regenerated by OASIS v0.4.5 Regenerated by OASIS v0.4.5
Visit http://oasis.forge.ocamlcore.org for more information and Visit http://oasis.forge.ocamlcore.org for more information and
@ -6861,7 +6861,7 @@ let setup_t =
alpha_features = []; alpha_features = [];
beta_features = []; beta_features = [];
name = "sequence"; name = "sequence";
version = "0.5.5"; version = "0.6";
license = license =
OASISLicense.DEP5License OASISLicense.DEP5License
(OASISLicense.DEP5Unit (OASISLicense.DEP5Unit
@ -7280,7 +7280,7 @@ let setup_t =
}; };
oasis_fn = Some "_oasis"; oasis_fn = Some "_oasis";
oasis_version = "0.4.5"; oasis_version = "0.4.5";
oasis_digest = Some "\179Sa\175xP\026d\164\216\201\198\001\028\141O"; oasis_digest = Some "\224\020Z\173\146\131E\193\nn\225\205\167u\192\196";
oasis_exec = None; oasis_exec = None;
oasis_setup_args = []; oasis_setup_args = [];
setup_update = false setup_update = false

View file

@ -124,11 +124,16 @@ let test_sort_uniq () =
|> S.to_list |> S.to_list
|> OUnit.assert_equal [1;2;3;4;5;42] |> OUnit.assert_equal [1;2;3;4;5;42]
let test_group () = let test_group_succ () =
[1;2;3;3;2;2;3;4] [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]] |> 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 () = let test_uniq () =
[1;2;2;3;4;4;4;3;3] [1;2;2;3;4;4;4;3;3]
|> S.of_list |> S.uniq ?eq:None |> S.to_list |> S.of_list |> S.uniq ?eq:None |> S.to_list
@ -203,6 +208,19 @@ let test_take () =
OUnit.assert_equal ~printer:pp_ilist [1;2;3;4;5] l; 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 test_regression1 () =
let s = S.(take 10 (repeat 1)) in let s = S.(take 10 (repeat 1)) in
OUnit.assert_bool "not empty" (not (S.is_empty s)); OUnit.assert_bool "not empty" (not (S.is_empty s));
@ -225,8 +243,9 @@ let suite =
"test_persistent" >:: test_persistent; "test_persistent" >:: test_persistent;
"test_big_persistent" >:: test_big_persistent; "test_big_persistent" >:: test_big_persistent;
"test_sort" >:: test_sort; "test_sort" >:: test_sort;
"test_sort_uniq" >:: test_sort; "test_sort_uniq" >:: test_sort_uniq;
"test_group" >:: test_group; "test_group_succ_by" >:: test_group_succ;
"test_group_by" >:: test_group_by;
"test_uniq" >:: test_uniq; "test_uniq" >:: test_uniq;
"test_product" >:: test_product; "test_product" >:: test_product;
"test_join" >:: test_join; "test_join" >:: test_join;
@ -237,5 +256,8 @@ let suite =
"test_hashtbl" >:: test_hashtbl; "test_hashtbl" >:: test_hashtbl;
"test_int_range" >:: test_int_range; "test_int_range" >:: test_int_range;
"test_take" >:: test_take; "test_take" >:: test_take;
"test_fold_while" >:: test_fold_while;
"test_buff" >:: test_buff;
"test_for_all" >:: test_for_all;
"test_regression1" >:: test_regression1; "test_regression1" >:: test_regression1;
] ]