From 3912b288e880f8df2d78e17b36096b12b2aad107 Mon Sep 17 00:00:00 2001 From: David Chemouil Date: Mon, 9 Nov 2020 17:47:06 +0100 Subject: [PATCH] add List.combine_chop and corresponding (and&) synchronized product --- src/core/CCList.ml | 25 +++++++++++++++++++++++++ src/core/CCList.mli | 22 ++++++++++++++++++++++ src/core/CCListLabels.mli | 21 +++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/src/core/CCList.ml b/src/core/CCList.ml index d42c56b9..2b9147c2 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -572,6 +572,29 @@ let combine_gen l1 l2 = res1 = res2) *) +let combine_chop l1 l2 = + let rec direct i l1 l2 = match l1, l2 with + | (_, []) | ([], _) -> [] + | _ when i=0 -> safe l1 l2 [] + | (x1::l1', x2::l2') -> (x1, x2) :: direct (i-1) l1' l2' + and safe l1 l2 acc = match l1, l2 with + | ([], _) | (_, []) -> List.rev acc + | (x1::l1', x2::l2') -> safe l1' l2' @@ (x1, x2) :: acc + in + direct direct_depth_default_ l1 l2 + +(*$T + (combine_chop [] []) = [] + (combine_chop [1] []) = [] + (combine_chop [] [1]) = [] + (combine_chop (1--1025) (1--1026)) = List.combine (1--1025) (1--1025) + (combine_chop (1--1026) (1--1025)) = List.combine (1--1025) (1--1025) + combine_chop [1;2;3] [3;2;1] = List.combine [1;2;3] [3;2;1] + combine_chop (1 -- 100_000) (1 -- 100_000) = List.combine (1 -- 100_000) (1 -- 100_000) + combine_chop (1 -- 100_001) (1 -- 100_000) = List.combine (1 -- 100_000) (1 -- 100_000) +*) + + let split l = let rec direct i l = match l with | [] -> [], [] @@ -1786,6 +1809,8 @@ module Infix = struct let (>>=) = (>>=) let[@inline] monoid_product l1 l2 = product (fun x y -> x,y) l1 l2 end) + + let (and&) = combine_chop end include Infix diff --git a/src/core/CCList.mli b/src/core/CCList.mli index 12cfb90c..fad47f17 100644 --- a/src/core/CCList.mli +++ b/src/core/CCList.mli @@ -138,6 +138,11 @@ val combine_gen : 'a list -> 'b list -> ('a * 'b) gen @since 1.2, but only @since 2.2 with labels *) +val combine_chop : 'a list -> 'b list -> ('a * 'b) list +(** [combine [a1; …; am] [b1; …; bn]] is [[(a1,b1); …; (am,bm)]] if m <= n. + Like {!combine} but stops at the shortest list rather than raising. + @since 3.1 *) + val split : ('a * 'b) t -> 'a t * 'b t (** [split [(a1,b1); …; (an,bn)]] is [([a1; …; an], [b1; …; bn])]. Transform a list of pairs into a pair of lists. @@ -854,6 +859,23 @@ module Infix : sig (** Let operators on OCaml >= 4.08.0, nothing otherwise @since 2.8 *) include CCShimsMkLet_.S with type 'a t_let := 'a list + + val (and&) : 'a list -> 'b list -> ('a * 'b) list + (** [(and&)] is [combine_chop]. It allows to perform a synchronized product between two lists, + stopping gently at the shortest. Usable both with [let+] and [let*]. + {[ + # let f xs ys zs = + let+ x = xs + and& y = ys + and& z = zs in + x + y + z;; + val f : int list -> int list -> int list -> int list = + # f [1;2] [5;6;7] [10;10];; + - : int list = [16; 18] + ]} + @since 3.1 + *) + end (** Let operators on OCaml >= 4.08.0, nothing otherwise diff --git a/src/core/CCListLabels.mli b/src/core/CCListLabels.mli index 61734064..e5176fa0 100644 --- a/src/core/CCListLabels.mli +++ b/src/core/CCListLabels.mli @@ -142,6 +142,11 @@ val combine_gen : 'a list -> 'b list -> ('a * 'b) gen @since 1.2, but only @since 2.2 with labels *) +val combine_chop : 'a list -> 'b list -> ('a * 'b) list +(** [combine [a1; …; am] [b1; …; bn]] is [[(a1,b1); …; (am,bm)]] if m <= n. + Like {!combine} but stops at the shortest list rather than raising. + @since 3.1 *) + val split : ('a * 'b) t -> 'a t * 'b t (** [split [(a1,b1); …; (an,bn)]] is [([a1; …; an], [b1; …; bn])]. Transform a list of pairs into a pair of lists. @@ -832,6 +837,22 @@ module Infix : sig (** Let operators on OCaml >= 4.08.0, nothing otherwise @since 2.8 *) include CCShimsMkLet_.S with type 'a t_let := 'a list + + val (and&) : 'a list -> 'b list -> ('a * 'b) list + (** [(and&)] is [combine_chop]. It allows to perform a synchronized product between two lists, + stopping gently at the shortest. Usable both with [let+] and [let*]. + {[ + # let f xs ys zs = + let+ x = xs + and& y = ys + and& z = zs in + x + y + z;; + val f : int list -> int list -> int list -> int list = + # f [1;2] [5;6;7] [10;10];; + - : int list = [16; 18] + ]} + @since 3.1 + *) end (** Let operators on OCaml >= 4.08.0, nothing otherwise