use Seq, remove Stream entirely to be ready for OCaml 5.0; add of_gen_once

This commit is contained in:
Simon Cruanes 2022-03-19 10:24:04 -04:00
parent 65ab9376b0
commit 173da38366
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
5 changed files with 55 additions and 71 deletions

View file

@ -13,6 +13,7 @@ build: [
depends: [ depends: [
"base-bytes" "base-bytes"
"result" "result"
"seq"
"ocaml" { >= "4.03.0" } "ocaml" { >= "4.03.0" }
"dune" { >= "1.1" } "dune" { >= "1.1" }
"dune-configurator" "dune-configurator"

View file

@ -344,14 +344,11 @@ module MList = struct
let to_gen l = _to_next () l let to_gen l = _to_next () l
let to_stream l = let to_seq l =
Stream.from (_to_next 42 l) (* 42=magic cookiiiiiie *)
let to_klist l =
let rec make (l,i) () = match l with let rec make (l,i) () = match l with
| Nil -> `Nil | Nil -> Seq.Nil
| Cons (_, n, tl) when i = !n -> make (!tl,0) () | Cons (_, n, tl) when i = !n -> make (!tl,0) ()
| Cons (a, _, _) -> `Cons (a.(i), make (l,i+1)) | Cons (a, _, _) -> Seq.Cons (a.(i), make (l,i+1))
in make (l,0) in make (l,0)
end end
@ -361,31 +358,22 @@ let persistent seq =
(*$R (*$R
let printer = pp_ilist in let printer = pp_ilist in
let stream = Stream.from (fun i -> if i < 5 then Some i else None) in let iter = of_gen_once (let i=ref (-1) in fun() -> incr i; if !i < 5 then Some !i else None) in
let seq = of_stream stream in (* consume iter into a persistent version of itself *)
OUnit.assert_equal ~printer [0;1;2;3;4] (seq |> to_list); let iter' = persistent iter in
OUnit.assert_equal ~printer [] (seq |> to_list); OUnit.assert_raises OneShotSequence (fun () -> iter |> to_list);
OUnit.assert_equal ~printer [0;1;2;3;4] (iter' |> to_list);
OUnit.assert_equal ~printer [0;1;2;3;4] (iter' |> to_list);
OUnit.assert_equal ~printer [0;1;2;3;4] (iter' |> to_seq_persistent |> of_seq |> to_list);
*) *)
(*$R (*$R
let printer = pp_ilist in let printer = pp_ilist in
let stream = Stream.from (fun i -> if i < 5 then Some i else None) in let iter = (0 -- 10_000) in
let seq = of_stream stream in let iter' = persistent iter in
(* consume seq into a persistent version of itself *) OUnit.assert_equal 10_001 (length iter');
let seq' = persistent seq in OUnit.assert_equal 10_001 (length iter');
OUnit.assert_equal ~printer [] (seq |> to_list); OUnit.assert_equal ~printer [0;1;2;3] (iter' |> take 4 |> to_list);
OUnit.assert_equal ~printer [0;1;2;3;4] (seq' |> to_list);
OUnit.assert_equal ~printer [0;1;2;3;4] (seq' |> to_list);
OUnit.assert_equal ~printer [0;1;2;3;4] (seq' |> to_stream |> of_stream |> to_list);
*)
(*$R
let printer = pp_ilist in
let seq = (0 -- 10_000) in
let seq' = persistent seq in
OUnit.assert_equal 10_001 (length seq');
OUnit.assert_equal 10_001 (length seq');
OUnit.assert_equal ~printer [0;1;2;3] (seq' |> take 4 |> to_list);
*) *)
type 'a lazy_state = type 'a lazy_state =
@ -542,8 +530,7 @@ let[@inline] product outer inner k =
outer (fun x -> inner (fun y -> k (x,y))) outer (fun x -> inner (fun y -> k (x,y)))
(*$R (*$R
let stream = Stream.from (fun i -> if i < 3 then Some i else None) in let a = 0 -- 2 in
let a = of_stream stream in
let b = of_list ["a";"b";"c"] in let b = of_list ["a";"b";"c"] in
let s = product a b |> map (fun (x,y) -> y,x) let s = product a b |> map (fun (x,y) -> y,x)
|> to_list |> List.sort compare in |> to_list |> List.sort compare in
@ -1041,11 +1028,13 @@ let array_slice a i j k =
k a.(idx); (* iterate on sub-array *) k a.(idx); (* iterate on sub-array *)
done done
let of_stream s k = Stream.iter k s let rec of_seq l k = match l() with
| Seq.Nil -> ()
| Seq.Cons (x,tl) -> k x; of_seq tl k
let to_stream seq = let to_seq_persistent seq =
let l = MList.of_iter seq in let l = MList.of_iter seq in
MList.to_stream l MList.to_seq l
let[@inline] to_stack s seq = iter (fun x -> Stack.push x s) seq let[@inline] to_stack s seq = iter (fun x -> Stack.push x s) seq
@ -1169,29 +1158,26 @@ let to_set (type s) (type v) m seq =
S.empty seq S.empty seq
type 'a gen = unit -> 'a option type 'a gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
(* consume the generator to build a MList *)
let rec of_gen1_ g k = match g () with
| None -> ()
| Some x -> k x; of_gen1_ g k
let of_gen_once g =
let first = ref true in
fun k ->
if !first then first := false else raise OneShotSequence;
of_gen1_ g k
let of_gen g = let of_gen g =
(* consume the generator to build a MList *) let l = MList.of_iter (of_gen1_ g) in
let rec iter1 k = match g () with
| None -> ()
| Some x -> k x; iter1 k
in
let l = MList.of_iter iter1 in
MList.to_iter l MList.to_iter l
let to_gen seq = let to_gen seq =
let l = MList.of_iter seq in let l = MList.of_iter seq in
MList.to_gen l MList.to_gen l
let rec of_klist l k = match l() with
| `Nil -> ()
| `Cons (x,tl) -> k x; of_klist tl k
let to_klist seq =
let l = MList.of_iter seq in
MList.to_klist l
(** {2 Functorial conversions between sets and iterators} *) (** {2 Functorial conversions between sets and iterators} *)
module Set = struct module Set = struct

View file

@ -25,7 +25,7 @@
(i.e. calling it several times always iterates on the same set of (i.e. calling it several times always iterates on the same set of
elements, for instance List.iter or Map.iter), then elements, for instance List.iter or Map.iter), then
the resulting {!t} object is also repeatable. For {b one-time iter functions} the resulting {!t} object is also repeatable. For {b one-time iter functions}
such as iteration on a file descriptor or a {!Stream}, such as iteration on a file descriptor or a {!Seq},
the {!persistent} function can be used to iterate and store elements in the {!persistent} function can be used to iterate and store elements in
a memory structure; the result is an iterator that iterates on the elements a memory structure; the result is an iterator that iterates on the elements
of this memory structure, cheaply and repeatably. of this memory structure, cheaply and repeatably.
@ -567,11 +567,14 @@ 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_seq : 'a Seq.t -> 'a t
(** Iterator of elements of a stream (usable only once) *) (** Iterator of elements of a {!Seq.t}.
@since NEXT_RELEASE *)
val to_stream : 'a t -> 'a Stream.t val to_seq_persistent : 'a t -> 'a Seq.t
(** Convert to a stream. linear in memory and time (a copy is made in memory) *) (** Convert to a {!Seq}. Linear in memory and time (a copy is made in memory).
This does not work on infinite iterators.
@since NEXT_RELEASE *)
val to_stack : 'a Stack.t -> 'a t -> unit val to_stack : 'a Stack.t -> 'a t -> unit
(** Push elements of the iterator on the stack *) (** Push elements of the iterator on the stack *)
@ -648,20 +651,18 @@ val to_set : (module Set.S with type elt = 'a and type t = 'b) -> 'a t -> 'b
(** Convert the iterator to a set, given the proper set module *) (** Convert the iterator 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]
val of_gen : 'a gen -> 'a t val of_gen : 'a gen -> 'a t
(** Traverse eagerly the generator and build an iterator from it *) (** Traverse eagerly the generator and build an iterator from it *)
val of_gen_once : 'a gen -> 'a t
(** One shot iterator using this generator.
It must not be traversed twice.
@since NEXT_RELEASE *)
val to_gen : 'a t -> 'a gen val to_gen : 'a t -> 'a gen
(** Make the iterator persistent (O(n)) and then iterate on it. Eager. *) (** Make the iterator persistent (O(n)) and then iterate on it. Eager. *)
val of_klist : 'a klist -> 'a t
(** Iterate on the lazy list *)
val to_klist : 'a t -> 'a klist
(** Make the iterator persistent and then iterate on it. Eager. *)
(** {2 Sets} *) (** {2 Sets} *)
module Set : sig module Set : sig

View file

@ -531,11 +531,14 @@ 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_seq : 'a Seq.t -> 'a t
(** Iterator of elements of a stream (usable only once) *) (** Iterator of elements of a {!Seq.t}.
@since NEXT_RELEASE *)
val to_stream : 'a t -> 'a Stream.t val to_seq_persistent : 'a t -> 'a Seq.t
(** Convert to a stream. linear in memory and time (a copy is made in memory) *) (** Convert to a {!Seq}. Linear in memory and time (a copy is made in memory).
This does not work on infinite iterators.
@since NEXT_RELEASE *)
val to_stack : 'a Stack.t -> 'a t -> unit val to_stack : 'a Stack.t -> 'a t -> unit
(** Push elements of the iterator on the stack *) (** Push elements of the iterator on the stack *)
@ -613,7 +616,6 @@ val to_set : (module Set.S with type elt = 'a and type t = 'b) -> 'a t -> 'b
(** Convert the iterator to a set, given the proper set module *) (** Convert the iterator 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]
val of_gen : 'a gen -> 'a t val of_gen : 'a gen -> 'a t
(** Traverse eagerly the generator and build an iterator from it *) (** Traverse eagerly the generator and build an iterator from it *)
@ -621,12 +623,6 @@ val of_gen : 'a gen -> 'a t
val to_gen : 'a t -> 'a gen val to_gen : 'a t -> 'a gen
(** Make the iterator persistent (O(n)) and then iterate on it. Eager. *) (** Make the iterator persistent (O(n)) and then iterate on it. Eager. *)
val of_klist : 'a klist -> 'a t
(** Iterate on the lazy list *)
val to_klist : 'a t -> 'a klist
(** Make the iterator persistent and then iterate on it. Eager. *)
(** {3 Sets} *) (** {3 Sets} *)
module Set : sig module Set : sig

View file

@ -15,7 +15,7 @@
(wrapped false) (wrapped false)
(modules Iter IterLabels Iter_shims_) (modules Iter IterLabels Iter_shims_)
(flags :standard -nolabels) (flags :standard -nolabels)
(libraries bytes result)) (libraries bytes result seq))
(env (env