diff --git a/src/core/CCList.ml b/src/core/CCList.ml index 48db53c0..efc614de 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -233,6 +233,28 @@ let fold_map f acc l = fold_map (fun acc x -> x::acc, x) [] l = (List.rev l, l)) *) +let fold_map_i f acc l = + let rec aux f acc i map_acc l = match l with + | [] -> acc, List.rev map_acc + | x :: l' -> + let acc, y = f acc i x in + aux f acc (i+1) (y :: map_acc) l' + in + aux f acc 0 [] l + +let fold_on_map ~f ~reduce acc l = + let rec aux acc l = match l with + | [] -> acc + | x :: l' -> + let acc = reduce acc (f x) in + aux acc l' + in + aux acc l + +(*$= + 6 (fold_on_map ~f:int_of_string ~reduce:(+) 0 ["1";"2";"3"]) +*) + let scan_left f acc l = let rec aux f acc l_acc l = match l with | [] -> List.rev l_acc @@ -290,6 +312,15 @@ let fold_filter_map f acc l = 0 (1--10)) *) +let fold_filter_map_i f acc l = + let rec aux f acc i map_acc l = match l with + | [] -> acc, List.rev map_acc + | x :: l' -> + let acc, y = f acc i x in + aux f acc (i+1) (cons_maybe y map_acc) l' + in + aux f acc 0 [] l + let fold_flat_map f acc l = let rec aux f acc map_acc l = match l with | [] -> acc, List.rev map_acc @@ -305,6 +336,15 @@ let fold_flat_map f acc l = fold_flat_map (fun acc x->acc+x, [pf "%d" x; pf "a%d" x]) 0 [1;2;3]) *) +let fold_flat_map_i f acc l = + let rec aux f acc i map_acc l = match l with + | [] -> acc, List.rev map_acc + | x :: l' -> + let acc, y = f acc i x in + aux f acc (i+1) (List.rev_append y map_acc) l' + in + aux f acc 0 [] l + (*$Q Q.(list int) (fun l -> \ fold_flat_map (fun acc x -> x::acc, [x;x+10]) [] l = \ @@ -387,6 +427,25 @@ let flat_map f l = List.length (flat_map (fun x->[x]) (1--300_000)) = 300_000 *) +let flat_map_i f l = + let rec aux f i l kont = match l with + | [] -> kont [] + | x::l' -> + let y = f i x in + let kont' tail = match y with + | [] -> kont tail + | [x] -> kont (x :: tail) + | [x;y] -> kont (x::y::tail) + | l -> kont (append l tail) + in + aux f (i+1) l' kont' + in + aux f 0 l (fun l->l) + +(*$= + [1;2;2;3;3;3] (flat_map_i (fun i x->replicate (i+1) x) [1;2;3]) +*) + let flatten l = fold_right append l [] (*$T diff --git a/src/core/CCList.mli b/src/core/CCList.mli index 64430bb0..d7ea52ad 100644 --- a/src/core/CCList.mli +++ b/src/core/CCList.mli @@ -73,6 +73,16 @@ val fold_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a list -> 'acc * 'b list list to another list. @since 0.14 *) +val fold_map_i : ('acc -> int -> 'a -> 'acc * 'b) -> 'acc -> 'a list -> 'acc * 'b list +(** [fold_map_i f init l] is a [foldi]-like function, but it also maps the + list to another list. + @since NEXT_RELEASE *) + +val fold_on_map : f:('a -> 'b) -> reduce:('acc -> 'b -> 'acc) -> 'acc -> 'a list -> 'acc +(** [fold_on_map ~f ~reduce init l] combines [map f] and [fold_left reduce init] + in one operation. + @since NEXT_RELEASE *) + val scan_left : ('acc -> 'a -> 'acc) -> 'acc -> 'a list -> 'acc list (** [scan_left f init l] returns the list [[init; f init x0; f (f init x0) x1; ...]] where [x0], [x1], etc. are the elements of [l]. @@ -89,11 +99,21 @@ val fold_filter_map : ('acc -> 'a -> 'acc * 'b option) -> 'acc -> 'a list -> 'ac generates a list of output in a way similar to {!filter_map}. @since 0.17 *) +val fold_filter_map_i : ('acc -> int -> 'a -> 'acc * 'b option) -> 'acc -> 'a list -> 'acc * 'b list +(** [fold_filter_map_i f init l] is a [foldi]-like function, but also + generates a list of output in a way similar to {!filter_map}. + @since NEXT_RELEASE *) + val fold_flat_map : ('acc -> 'a -> 'acc * 'b list) -> 'acc -> 'a list -> 'acc * 'b list (** [fold_flat_map f acc l] is a [fold_left]-like function, but it also maps the list to a list of lists that is then [flatten]'d. @since 0.14 *) +val fold_flat_map_i : ('acc -> int -> 'a -> 'acc * 'b list) -> 'acc -> 'a list -> 'acc * 'b list +(** [fold_flat_map_i f acc l] is a [fold_left]-like function, but it also maps the + list to a list of lists that is then [flatten]'d. + @since NEXT_RELEASE *) + val count : ('a -> bool) -> 'a list -> int (** [count p l] counts how many elements of [l] satisfy predicate [p]. @since 1.5, but only @@ -150,6 +170,12 @@ val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val flat_map : ('a -> 'b t) -> 'a t -> 'b t (** Map and flatten at the same time (safe). Evaluation order is not guaranteed. *) +val flat_map_i : (int -> 'a -> 'b t) -> 'a t -> 'b t +(** Map with index and flatten at the same time (safe). + Evaluation order is not guaranteed. + @since NEXT_RELEASE +*) + val flatten : 'a t t -> 'a t (** Safe flatten. Concatenate a list of lists. *) diff --git a/src/core/CCListLabels.mli b/src/core/CCListLabels.mli index bc914720..742cee5d 100644 --- a/src/core/CCListLabels.mli +++ b/src/core/CCListLabels.mli @@ -73,6 +73,16 @@ val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a list -> 'acc * 'b list to another list. @since 0.14 *) +val fold_map_i : f:('acc -> int -> 'a -> 'acc * 'b) -> init:'acc -> 'a list -> 'acc * 'b list +(** [fold_map_i f init l] is a [foldi]-like function, but it also maps the + list to another list. + @since NEXT_RELEASE *) + +val fold_on_map : f:('a -> 'b) -> reduce:('acc -> 'b -> 'acc) -> init:'acc -> 'a list -> 'acc +(** [fold_on_map ~f ~reduce init l] combines [map f] and [fold_left reduce init] + in one operation. + @since NEXT_RELEASE *) + val scan_left : f:('acc -> 'a -> 'acc) -> init:'acc -> 'a list -> 'acc list (** [scan_left ~f ~init l] returns the list [[init; f init x0; f (f init x0) x1; ...]] where [x0], [x1], etc. are the elements of [l]. @@ -89,11 +99,21 @@ val fold_filter_map : f:('acc -> 'a -> 'acc * 'b option) -> init:'acc -> 'a list generates a list of output in a way similar to {!filter_map}. @since 0.17 *) +val fold_filter_map_i : f:('acc -> int -> 'a -> 'acc * 'b option) -> init:'acc -> 'a list -> 'acc * 'b list +(** [fold_filter_map_i f init l] is a [foldi]-like function, but also + generates a list of output in a way similar to {!filter_map}. + @since NEXT_RELEASE *) + val fold_flat_map : f:('acc -> 'a -> 'acc * 'b list) -> init:'acc -> 'a list -> 'acc * 'b list (** [fold_flat_map f acc l] is a [fold_left]-like function, but it also maps the list to a list of lists that is then [flatten]'d. @since 0.14 *) +val fold_flat_map_i : f:('acc -> int -> 'a -> 'acc * 'b list) -> init:'acc -> 'a list -> 'acc * 'b list +(** [fold_flat_map_i f acc l] is a [fold_left]-like function, but it also maps the + list to a list of lists that is then [flatten]'d. + @since NEXT_RELEASE *) + val count : f:('a -> bool) -> 'a list -> int (** [count p l] counts how many elements of [l] satisfy predicate [p]. @since 1.5, but only @@ -150,6 +170,12 @@ val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val flat_map : f:('a -> 'b t) -> 'a t -> 'b t (** Map and flatten at the same time (safe). Evaluation order is not guaranteed. *) +val flat_map_i : f:(int -> 'a -> 'b t) -> 'a t -> 'b t +(** Map with index and flatten at the same time (safe). + Evaluation order is not guaranteed. + @since NEXT_RELEASE +*) + val flatten : 'a t t -> 'a t (** Safe flatten. Concatenate a list of lists. *) diff --git a/src/data/CCGraph.mli b/src/data/CCGraph.mli index f711003f..abf43210 100644 --- a/src/data/CCGraph.mli +++ b/src/data/CCGraph.mli @@ -40,7 +40,7 @@ type 'a sequence = ('a -> unit) -> unit @deprecate see {!iter} instead *) [@@ocaml.deprecated "see iter"] -type 'a sequence_once = 'a sequence +type 'a sequence_once = 'a iter (** Iter that should be used only once @deprecate see {!iter_once} instead *) [@@ocaml.deprecated "see iter_once"]