add CCKList.{unfold,of_gen}

This commit is contained in:
Simon Cruanes 2015-08-31 13:16:35 +02:00
parent 2be5f2f638
commit 6f8882b8af
2 changed files with 46 additions and 0 deletions

View file

@ -151,6 +151,15 @@ let rec cycle l () = append l (cycle l) ()
cycle (of_list [1;2]) |> take 5 |> to_list = [1;2;1;2;1]
*)
let rec unfold f acc () = match f acc with
| None -> `Nil
| Some (x, acc') -> `Cons (x, unfold f acc')
(*$T
let f = function 10 -> None | x -> Some (x, x+1) in \
unfold f 0 |> to_list = [0;1;2;3;4;5;6;7;8;9]
*)
let rec flat_map f l () = match l () with
| `Nil -> `Nil
| `Cons (x, l') ->
@ -311,6 +320,35 @@ let to_gen l =
l := l';
Some x
type 'a of_gen_state =
| Of_gen_thunk of 'a gen
| Of_gen_saved of [`Nil | `Cons of 'a * 'a t]
let of_gen g =
let rec consume r () = match !r with
| Of_gen_saved cons -> cons
| Of_gen_thunk g ->
begin match g() with
| None ->
r := Of_gen_saved `Nil;
`Nil
| Some x ->
let tl = consume (ref (Of_gen_thunk g)) in
let l = `Cons (x, tl) in
r := Of_gen_saved l;
l
end
in
consume (ref (Of_gen_thunk g))
(*$R
let g = let n = ref 0 in fun () -> Some (incr n; !n) in
let l = of_gen g in
assert_equal [1;2;3;4;5;6;7;8;9;10] (take 10 l |> to_list);
assert_equal [1;2;3;4;5;6;7;8;9;10] (take 10 l |> to_list);
assert_equal [11;12] (drop 10 l |> take 2 |> to_list);
*)
let sort ?(cmp=Pervasives.compare) l =
let l = to_list l in
of_list (List.sort cmp l)

View file

@ -56,6 +56,11 @@ val cycle : 'a t -> 'a t
(** Cycle through the iterator infinitely. The iterator shouldn't be empty.
@since 0.3.3 *)
val unfold : ('b -> ('a * 'b) option) -> 'b -> 'a t
(** [unfold f acc] calls [f acc] and:
- if [f acc = Some (x, acc')], yield [x], continue with [unfold f acc']
- if [f acc = None], stops
@since NEXT_RELEASE *)
val is_empty : 'a t -> bool
@ -185,6 +190,9 @@ val to_seq : 'a t -> 'a sequence
val to_gen : 'a t -> 'a gen
val of_gen : 'a gen -> 'a t
(** [of_gen g] consumes the generator and caches intermediate results
@since NEXT_RELEASE *)
(** {2 IO} *)