diff --git a/src/core/CCArray.ml b/src/core/CCArray.ml index c10a9ee2..32634263 100644 --- a/src/core/CCArray.ml +++ b/src/core/CCArray.ml @@ -53,6 +53,11 @@ module type S = sig val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b (** fold left on array, with index *) + val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a + (** fold left on array until a stop condition via [('a, `Stop)] is + indicated by the accumulator + @since NEXT_RELEASE *) + val iter : ('a -> unit) -> 'a t -> unit val iteri : (int -> 'a -> unit) -> 'a t -> unit @@ -276,6 +281,20 @@ let fold = Array.fold_left let foldi f acc a = _foldi f acc a 0 (Array.length a) +let fold_while f acc a = + let rec fold_while_i f acc i = + if i < Array.length a then + let acc, cont = f acc a.(i) in + match cont with + | `Stop -> acc + | `Continue -> fold_while_i f acc (i+1) + else acc + in fold_while_i f acc 0 + +(*$T + fold_while (fun acc b -> if b then acc+1, `Continue else acc, `Stop) 0 (Array.of_list [true;true;false;true]) = 2 +*) + let iter = Array.iter let iteri = Array.iteri @@ -480,6 +499,16 @@ module Sub = struct let foldi f acc a = _foldi f acc a.arr a.i a.j + let fold_while f acc a = + let rec fold_while_i f acc i = + if i < Array.length a.arr && i < a.j then + let acc, cont = f acc a.arr.(i) in + match cont with + | `Stop -> acc + | `Continue -> fold_while_i f acc (i+1) + else acc + in fold_while_i f acc a.i + let get a i = let j = a.i + i in if i<0 || j>=a.j then invalid_arg "Array.Sub.get"; diff --git a/src/core/CCArray.mli b/src/core/CCArray.mli index e3cf6dac..51665df7 100644 --- a/src/core/CCArray.mli +++ b/src/core/CCArray.mli @@ -50,10 +50,15 @@ module type S = sig val length : _ t -> int - val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b + val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a - val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b - (** fold left on array, with index *) + val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a + (** Fold left on array, with index *) + + val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a + (** Fold left on array until a stop condition via [('a, `Stop)] is + indicated by the accumulator + @since NEXT_RELEASE *) val iter : ('a -> unit) -> 'a t -> unit diff --git a/src/core/CCList.ml b/src/core/CCList.ml index 451e73c4..48846818 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -116,6 +116,17 @@ let fold_right f l acc = l = fold_right (fun x y->x::y) l []) *) +let rec fold_while f acc = function + | [] -> acc + | e::l -> let acc, cont = f acc e in + match cont with + | `Stop -> acc + | `Continue -> fold_while f acc l + +(*$T + fold_while (fun acc b -> if b then acc+1, `Continue else acc, `Stop) 0 [true;true;false;true] = 2 +*) + let init len f = let rec init_rec acc i f = if i=0 then f i :: acc diff --git a/src/core/CCList.mli b/src/core/CCList.mli index 6f62288e..8400351a 100644 --- a/src/core/CCList.mli +++ b/src/core/CCList.mli @@ -48,6 +48,11 @@ val filter : ('a -> bool) -> 'a t -> 'a t val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b (** Safe version of [fold_right] *) +val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a +(** Fold until a stop condition via [('a, `Stop)] is + indicated by the accumulator + @since NEXT_RELEASE *) + val init : int -> (int -> 'a) -> 'a t (** Same as [Array.init] @since 0.6 *)