Skip to content

Commit

Permalink
CCList: add unfold
Browse files Browse the repository at this point in the history
  • Loading branch information
benbellick committed Dec 5, 2023
1 parent 77bfa34 commit 5326871
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/core/CCList.ml
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ let fold_flat_map_i f acc l =
in
aux f acc 0 [] l

let rec unfold f seed =
match f seed with
| None -> []
| Some (v, next) -> v :: unfold f next

[@@@iflt 5.1]

(* keep this because it's tailrec for < 5.1 *)
Expand Down
10 changes: 10 additions & 0 deletions src/core/CCList.mli
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ val fold_flat_map_i :
list to a list of lists that is then [flatten]'d.
@since 2.8 *)

val unfold : ('seed -> ('b * 'seed) option) -> 'seed -> 'b list
(** [unfold f init] builds up a list from a seed value.
When [f] produces [Some (next_seed, value)], [value] is added to the output list and
[next_seed] is used in the next call to [f]. However,
when [f] produces [None], list production ends.
{b NOTE} if [f] never produces [None], then a {b stack overflow will occur}. Therefore,
great care must be taken to ensure that [f] will produce [None].
@since 3.13
*)

val count : ('a -> bool) -> 'a list -> int
(** [count p l] counts how many elements of [l] satisfy predicate [p].
@since 1.5, but only
Expand Down
10 changes: 10 additions & 0 deletions src/core/CCListLabels.mli
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,16 @@ val fold_flat_map_i :
list to a list of lists that is then [flatten]'d.
@since 2.8 *)

val unfold : f:('seed -> ('b * 'seed) option) -> init:'seed -> 'b list
(** [unfold ~f ~init] builds up a list from a seed value.
When [f] produces [Some (next_seed, value)], [value] is added to the output list and
[next_seed] is used in the next call to [f]. However,
when [f] produces [None], list production ends.
{b NOTE} if [f] never produces [None], then a {b stack overflow will occur}. Therefore,
great care must be taken to ensure that [f] will produce [None].
@since 3.13
*)

val count : f:('a -> bool) -> 'a list -> int
(** [count ~f l] counts how many elements of [l] satisfy predicate [f].
@since 1.5, but only
Expand Down
10 changes: 10 additions & 0 deletions tests/core/t_list.ml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ q
= (List.rev l, flat_map (fun x -> [ x; x + 10 ]) l))
;;

t @@ fun () ->
let f x =
if x <= 5 then
Some (2 * x, x + 1)
else
None
in
unfold f 0 = [ 0; 2; 4; 6; 8; 10 ]
;;

t @@ fun () -> init 0 (fun _ -> 0) = [];;
t @@ fun () -> init 1 (fun x -> x) = [ 0 ];;
t @@ fun () -> init 1000 (fun x -> x) = 0 -- 999;;
Expand Down

0 comments on commit 5326871

Please sign in to comment.