mirror of
https://github.com/c-cube/iter.git
synced 2025-12-06 03:05:29 -05:00
add init,fold_map,fold_filter_map,sorted,diagonal,findi,…
This commit is contained in:
parent
b062ccfd70
commit
4748655708
3 changed files with 159 additions and 0 deletions
|
|
@ -48,6 +48,17 @@ let repeat x k = while true do k x done
|
|||
(seq |> take 3 |> to_list);
|
||||
*)
|
||||
|
||||
let init f yield =
|
||||
let rec aux i =
|
||||
yield (f i);
|
||||
aux (i+1)
|
||||
in
|
||||
aux 0
|
||||
|
||||
(*$=
|
||||
[0;1;2;3;4] (init (fun x->x) |> take 5 |> to_list)
|
||||
*)
|
||||
|
||||
let rec iterate f x k =
|
||||
k x;
|
||||
iterate f (f x) k
|
||||
|
|
@ -94,6 +105,28 @@ let foldi f init seq =
|
|||
OUnit.assert_equal [1, "world"; 0, "hello"] l;
|
||||
*)
|
||||
|
||||
let fold_map f init seq yield =
|
||||
let r = ref init in
|
||||
seq
|
||||
(fun x ->
|
||||
let acc', y = f !r x in
|
||||
r := acc';
|
||||
yield y)
|
||||
|
||||
(*$= & ~printer:Q.Print.(list int)
|
||||
[0;1;3;5] (0--3 |> fold_map (fun prev x -> x,prev+x) 0 |> to_list)
|
||||
*)
|
||||
|
||||
let fold_filter_map f init seq yield =
|
||||
let r = ref init in
|
||||
seq
|
||||
(fun x ->
|
||||
let acc', y = f !r x in
|
||||
r := acc';
|
||||
match y with
|
||||
| None -> ()
|
||||
| Some y' -> yield y')
|
||||
|
||||
let map f seq k = seq (fun x -> k (f x))
|
||||
|
||||
let mapi f seq k =
|
||||
|
|
@ -320,6 +353,23 @@ let sort ?(cmp=Pervasives.compare) seq =
|
|||
|> OUnit.assert_equal [100;99;98;97]
|
||||
*)
|
||||
|
||||
exception Exit_sorted
|
||||
|
||||
let sorted ?(cmp=Pervasives.compare) seq =
|
||||
let prev = ref None in
|
||||
try
|
||||
seq (fun x -> match !prev with
|
||||
| Some y when cmp y x > 0 -> raise Exit_sorted
|
||||
| _ -> prev := Some x);
|
||||
true
|
||||
with Exit_sorted -> false
|
||||
|
||||
(*$T
|
||||
of_list [1;2;3;4] |> sorted
|
||||
not (of_list [1;2;3;0;4] |> sorted)
|
||||
sorted empty
|
||||
*)
|
||||
|
||||
let group_succ_by ?(eq=fun x y -> x = y) seq k =
|
||||
let cur = ref [] in
|
||||
seq (fun x ->
|
||||
|
|
@ -413,6 +463,16 @@ let product outer inner k =
|
|||
let product2 outer inner k =
|
||||
outer (fun x -> inner (fun y -> k x y))
|
||||
|
||||
let rec diagonal l yield = match l with
|
||||
| [] -> ()
|
||||
| x::tail ->
|
||||
List.iter (fun y -> yield (x,y)) tail;
|
||||
diagonal tail yield
|
||||
|
||||
(*$=
|
||||
[0,1; 0,2; 1,2] (diagonal [0;1;2] |> to_list)
|
||||
*)
|
||||
|
||||
let join ~join_row s1 s2 k =
|
||||
s1 (fun a ->
|
||||
s2 (fun b ->
|
||||
|
|
@ -607,6 +667,25 @@ let find f seq =
|
|||
end;
|
||||
!r
|
||||
|
||||
let findi f seq =
|
||||
let i = ref 0 in
|
||||
let r = ref None in
|
||||
begin
|
||||
try
|
||||
seq
|
||||
(fun x -> match f !i x with
|
||||
| None -> incr i
|
||||
| Some _ as res -> r := res; raise ExitFind);
|
||||
with ExitFind -> ()
|
||||
end;
|
||||
!r
|
||||
|
||||
let find_pred f seq = find (fun x -> if f x then Some x else None) seq
|
||||
|
||||
let find_pred_exn f seq = match find_pred f seq with
|
||||
| Some x -> x
|
||||
| None -> raise Not_found
|
||||
|
||||
let length seq =
|
||||
let r = ref 0 in
|
||||
seq (fun _ -> incr r);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ val singleton : 'a -> 'a t
|
|||
val doubleton : 'a -> 'a -> 'a t
|
||||
(** Sequence with exactly two elements *)
|
||||
|
||||
val init : (int -> 'a) -> 'a t
|
||||
(** [init f] is the infinite sequence [f 0; f 1; f 2; …].
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val cons : 'a -> 'a t -> 'a t
|
||||
(** [cons x l] yields [x], then yields from [l].
|
||||
Same as [append (singleton x) l] *)
|
||||
|
|
@ -103,6 +107,17 @@ val fold : ('a -> '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 *)
|
||||
|
||||
val fold_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a t -> 'b t
|
||||
(** [fold_map f acc l] is like {!map}, but it carries some state as in
|
||||
{!fold}. The state is not returned, it is just used to thread some
|
||||
information to the map function.
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val fold_filter_map : ('acc -> 'a -> 'acc * 'b option) -> 'acc -> 'a t -> 'b t
|
||||
(** [fold_filter_map f acc l] is a {!fold_map}-like function, but the
|
||||
function can choose to skip an element by retuning [None].
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val map : ('a -> 'b) -> 'a t -> 'b t
|
||||
(** Map objects of the sequence into other elements, lazily *)
|
||||
|
||||
|
|
@ -129,6 +144,20 @@ val find : ('a -> 'b option) -> 'a t -> 'b option
|
|||
(** Find the first element on which the function doesn't return [None]
|
||||
@since 0.5 *)
|
||||
|
||||
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||
(** Indexed version of {!find}
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val find_pred : ('a -> bool) -> 'a t -> 'a option
|
||||
(** [find_pred p l] finds the first element of [l] that satisfies [p],
|
||||
or returns [None] if no element satisfies [p]
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val find_pred_exn : ('a -> bool) -> 'a t -> 'a
|
||||
(** Unsafe version of {!find_pred}
|
||||
@raise Not_found if no such element is found
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val length : 'a t -> int
|
||||
(** How long is the sequence? Forces the sequence. *)
|
||||
|
||||
|
|
@ -197,6 +226,10 @@ val sort : ?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] *)
|
||||
|
||||
val sorted : ?cmp:('a -> 'a -> int) -> 'a t -> bool
|
||||
(** Checks whether the sequence is sorted. Eager, same as {!sort}.
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
|
||||
(** Group equal consecutive elements.
|
||||
Formerly synonym to [group].
|
||||
|
|
@ -218,6 +251,11 @@ val product : 'a t -> 'b t -> ('a * 'b) t
|
|||
as required (several times), possibly by calling {!persistent} on it
|
||||
beforehand. *)
|
||||
|
||||
val diagonal : 'a list -> ('a * 'a) t
|
||||
(** All pairs of distinct positions of the list. [diagonal l] will
|
||||
return the list of [List.nth i l, List.nth j l] if [i < j].
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val product2 : 'a t -> 'b t -> ('a, 'b) t2
|
||||
(** Binary version of {!product}. Same requirements.
|
||||
@since 0.5 *)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ val singleton : 'a -> 'a t
|
|||
val doubleton : 'a -> 'a -> 'a t
|
||||
(** Sequence with exactly two elements *)
|
||||
|
||||
val init : f:(int -> 'a) -> 'a t
|
||||
(** [init f] is the infinite sequence [f 0; f 1; f 2; …].
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val cons : 'a -> 'a t -> 'a t
|
||||
(** [cons x l] yields [x], then yields from [l].
|
||||
Same as [append (singleton x) l] *)
|
||||
|
|
@ -81,6 +85,17 @@ val fold : f:('a -> '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 *)
|
||||
|
||||
val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a t -> 'b t
|
||||
(** [fold_map f acc l] is like {!map}, but it carries some state as in
|
||||
{!fold}. The state is not returned, it is just used to thread some
|
||||
information to the map function.
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val fold_filter_map : f:('acc -> 'a -> 'acc * 'b option) -> init:'acc -> 'a t -> 'b t
|
||||
(** [fold_filter_map f acc l] is a {!fold_map}-like function, but the
|
||||
function can choose to skip an element by retuning [None].
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val map : f:('a -> 'b) -> 'a t -> 'b t
|
||||
(** Map objects of the sequence into other elements, lazily *)
|
||||
|
||||
|
|
@ -105,6 +120,20 @@ val mem : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> bool
|
|||
val find : f:('a -> 'b option) -> 'a t -> 'b option
|
||||
(** Find the first element on which the function doesn't return [None] *)
|
||||
|
||||
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||
(** Indexed version of {!find}
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val find_pred : f:('a -> bool) -> 'a t -> 'a option
|
||||
(** [find_pred p l] finds the first element of [l] that satisfies [p],
|
||||
or returns [None] if no element satisfies [p]
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val find_pred_exn : f:('a -> bool) -> 'a t -> 'a
|
||||
(** Unsafe version of {!find_pred}
|
||||
@raise Not_found if no such element is found
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val length : 'a t -> int
|
||||
(** How long is the sequence? Forces the sequence. *)
|
||||
|
||||
|
|
@ -168,6 +197,10 @@ val sort : ?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] *)
|
||||
|
||||
val sorted : ?cmp:('a -> 'a -> int) -> 'a t -> bool
|
||||
(** Checks whether the sequence is sorted. Eager, same as {!sort}.
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
|
||||
(** Group equal consecutive elements.
|
||||
Formerly synonym to [group].
|
||||
|
|
@ -189,6 +222,11 @@ val product : 'a t -> 'b t -> ('a * 'b) t
|
|||
as required (several times), possibly by calling {!persistent} on it
|
||||
beforehand. *)
|
||||
|
||||
val diagonal : 'a list -> ('a * 'a) t
|
||||
(** All pairs of distinct positions of the list. [diagonal l] will
|
||||
return the list of [List.nth i l, List.nth j l] if [i < j].
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val product2 : 'a t -> 'b t -> ('a, 'b) t2
|
||||
(** Binary version of {!product}. Same requirements. *)
|
||||
|
||||
|
|
@ -382,6 +420,10 @@ val int_range_by : step:int -> start:int -> stop:int -> int t
|
|||
@since NEXT_RELEASE
|
||||
@raise Invalid_argument if [step=0] *)
|
||||
|
||||
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
|
||||
(** Convert the given set to a sequence. The set module must be provided. *)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue