add CCArray.{fold_map,scan_left} (close #101)

This commit is contained in:
Simon Cruanes 2017-03-09 21:41:38 +01:00
parent 6e97ee8c7c
commit d135f73c76
2 changed files with 53 additions and 0 deletions

View file

@ -71,6 +71,48 @@ let fold_while f acc a =
fold_while (fun acc b -> if b then acc+1, `Continue else acc, `Stop) 0 (Array.of_list [true;true;false;true]) = 2
*)
let fold_map f acc a =
let n = length a in
(* need special case for initializing the result *)
if n = 0 then acc, [||]
else (
let acc, b0 = f acc a.(0) in
let res = Array.make n b0 in
let acc = ref acc in
for i = 1 to n-1 do
let new_acc, b = f !acc a.(i) in
acc := new_acc;
res.(i) <- b;
done;
!acc, res
)
(*$=
(6, [|"1"; "2"; "3"|]) \
(fold_map (fun acc x->acc+x, string_of_int x) 0 [|1;2;3|])
*)
(*$Q
Q.(array int) (fun a -> \
fold_map (fun acc x -> x::acc, x) [] a = (List.rev @@ Array.to_list a, a))
*)
let scan_left f acc a =
let n = length a in
let res = Array.make (n+1) acc in
Array.iteri
(fun i x ->
let new_acc = f res.(i) x in
res.(i+1) <- new_acc)
a;
res
(*$= & ~printer:Q.Print.(array int)
[|0;1;3;6|] (scan_left (+) 0 [|1;2;3|])
[|0|] (scan_left (+) 0 [||])
*)
let iter = Array.iter
let iteri = Array.iteri

View file

@ -41,6 +41,17 @@ val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
indicated by the accumulator
@since 0.8 *)
val fold_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a t -> 'acc * 'b t
(** [fold_map f acc a] is a [fold_left]-like function, but it also maps the
array to another array.
@since NEXT_RELEASE *)
val scan_left : ('acc -> 'a -> 'acc) -> 'acc -> 'a t -> 'acc t
(** [scan_left f acc a] returns the array
[ [|acc; f acc x0; f (f acc a.(0)) a.(1); |] ]
@since NEXT_RELEASE *)
val iter : ('a -> unit) -> 'a t -> unit
val iteri : (int -> 'a -> unit) -> 'a t -> unit