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: [
"base-bytes"
"result"
"seq"
"ocaml" { >= "4.03.0" }
"dune" { >= "1.1" }
"dune-configurator"

View file

@ -344,14 +344,11 @@ module MList = struct
let to_gen l = _to_next () l
let to_stream l =
Stream.from (_to_next 42 l) (* 42=magic cookiiiiiie *)
let to_klist l =
let to_seq l =
let rec make (l,i) () = match l with
| Nil -> `Nil
| Nil -> Seq.Nil
| 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)
end
@ -361,31 +358,22 @@ let persistent seq =
(*$R
let printer = pp_ilist in
let stream = Stream.from (fun i -> if i < 5 then Some i else None) in
let seq = of_stream stream in
OUnit.assert_equal ~printer [0;1;2;3;4] (seq |> to_list);
OUnit.assert_equal ~printer [] (seq |> to_list);
let iter = of_gen_once (let i=ref (-1) in fun() -> incr i; if !i < 5 then Some !i else None) in
(* consume iter into a persistent version of itself *)
let iter' = persistent iter in
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
let printer = pp_ilist in
let stream = Stream.from (fun i -> if i < 5 then Some i else None) in
let seq = of_stream stream in
(* consume seq into a persistent version of itself *)
let seq' = persistent seq in
OUnit.assert_equal ~printer [] (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_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);
let iter = (0 -- 10_000) in
let iter' = persistent iter in
OUnit.assert_equal 10_001 (length iter');
OUnit.assert_equal 10_001 (length iter');
OUnit.assert_equal ~printer [0;1;2;3] (iter' |> take 4 |> to_list);
*)
type 'a lazy_state =
@ -542,8 +530,7 @@ let[@inline] product outer inner k =
outer (fun x -> inner (fun y -> k (x,y)))
(*$R
let stream = Stream.from (fun i -> if i < 3 then Some i else None) in
let a = of_stream stream in
let a = 0 -- 2 in
let b = of_list ["a";"b";"c"] in
let s = product a b |> map (fun (x,y) -> y,x)
|> to_list |> List.sort compare in
@ -1041,11 +1028,13 @@ let array_slice a i j k =
k a.(idx); (* iterate on sub-array *)
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
MList.to_stream l
MList.to_seq l
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
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 =
(* consume the generator to build a MList *)
let rec iter1 k = match g () with
| None -> ()
| Some x -> k x; iter1 k
in
let l = MList.of_iter iter1 in
let l = MList.of_iter (of_gen1_ g) in
MList.to_iter l
let to_gen seq =
let l = MList.of_iter seq in
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} *)
module Set = struct

View file

@ -25,7 +25,7 @@
(i.e. calling it several times always iterates on the same set of
elements, for instance List.iter or Map.iter), then
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
a memory structure; the result is an iterator that iterates on the elements
of this memory structure, cheaply and repeatably.
@ -567,11 +567,14 @@ val of_opt : 'a option -> 'a t
(** Iterate on 0 or 1 values.
@since 0.5.1 *)
val of_stream : 'a Stream.t -> 'a t
(** Iterator of elements of a stream (usable only once) *)
val of_seq : 'a Seq.t -> 'a t
(** Iterator of elements of a {!Seq.t}.
@since NEXT_RELEASE *)
val to_stream : 'a t -> 'a Stream.t
(** Convert to a stream. linear in memory and time (a copy is made in memory) *)
val to_seq_persistent : 'a t -> 'a Seq.t
(** 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
(** 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 *)
type 'a gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
val of_gen : 'a gen -> 'a t
(** Traverse eagerly the generator and build 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
(** 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} *)
module Set : sig

View file

@ -531,11 +531,14 @@ val of_opt : 'a option -> 'a t
(** Iterate on 0 or 1 values.
@since 0.5.1 *)
val of_stream : 'a Stream.t -> 'a t
(** Iterator of elements of a stream (usable only once) *)
val of_seq : 'a Seq.t -> 'a t
(** Iterator of elements of a {!Seq.t}.
@since NEXT_RELEASE *)
val to_stream : 'a t -> 'a Stream.t
(** Convert to a stream. linear in memory and time (a copy is made in memory) *)
val to_seq_persistent : 'a t -> 'a Seq.t
(** 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
(** 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 *)
type 'a gen = unit -> 'a option
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
val of_gen : 'a gen -> 'a t
(** Traverse eagerly the generator and build an iterator from it *)
@ -621,12 +623,6 @@ val of_gen : 'a gen -> 'a t
val to_gen : 'a t -> 'a gen
(** 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} *)
module Set : sig

View file

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