Map.filter_map and Set.filter_map
parent
e10e2bfa99
commit
1cd6e4451f
3
Changes
3
Changes
|
@ -112,6 +112,9 @@ Working version
|
||||||
- #7110: Added Printf.ikbprintf and Printf.ibprintf
|
- #7110: Added Printf.ikbprintf and Printf.ibprintf
|
||||||
(Muskan Garg, review by Gabriel Scherer and Florian Angeletti)
|
(Muskan Garg, review by Gabriel Scherer and Florian Angeletti)
|
||||||
|
|
||||||
|
- #9365: Set.filter_map and Map.filter_map
|
||||||
|
(Gabriel Scherer, review by Stephen Dolan and Nicolás Ojeda Bär)
|
||||||
|
|
||||||
### Other libraries:
|
### Other libraries:
|
||||||
|
|
||||||
- #9106: Register printer for Unix_error in win32unix, as in unix.
|
- #9106: Register printer for Unix_error in win32unix, as in unix.
|
||||||
|
|
|
@ -688,9 +688,8 @@ let build_transient ~(backend : (module Backend_intf.S))
|
||||||
~root_symbol:(Compilenv.current_unit_symbol ())
|
~root_symbol:(Compilenv.current_unit_symbol ())
|
||||||
in
|
in
|
||||||
let sets_of_closures =
|
let sets_of_closures =
|
||||||
Set_of_closures_id.Map.filter_map
|
function_declarations_map |> Set_of_closures_id.Map.filter_map
|
||||||
function_declarations_map
|
(fun key (fun_decls : Simple_value_approx.function_declarations) ->
|
||||||
~f:(fun key (fun_decls : Simple_value_approx.function_declarations) ->
|
|
||||||
if Set_of_closures_id.Set.mem key relevant_set_of_closures then
|
if Set_of_closures_id.Set.mem key relevant_set_of_closures then
|
||||||
Some fun_decls
|
Some fun_decls
|
||||||
else if begin
|
else if begin
|
||||||
|
|
|
@ -573,8 +573,8 @@ let prepare_to_simplify_set_of_closures ~env
|
||||||
set_of_closures.free_vars
|
set_of_closures.free_vars
|
||||||
in
|
in
|
||||||
let specialised_args =
|
let specialised_args =
|
||||||
Variable.Map.filter_map set_of_closures.specialised_args
|
set_of_closures.specialised_args |> Variable.Map.filter_map
|
||||||
~f:(fun param (spec_to : Flambda.specialised_to) ->
|
(fun param (spec_to : Flambda.specialised_to) ->
|
||||||
let keep =
|
let keep =
|
||||||
match only_for_function_decl with
|
match only_for_function_decl with
|
||||||
| None -> true
|
| None -> true
|
||||||
|
|
|
@ -33,8 +33,8 @@ module Transform = struct
|
||||||
what_to_specialise
|
what_to_specialise
|
||||||
else
|
else
|
||||||
let projections_by_function =
|
let projections_by_function =
|
||||||
Variable.Map.filter_map set_of_closures.function_decls.funs
|
set_of_closures.function_decls.funs |> Variable.Map.filter_map
|
||||||
~f:(fun _fun_var (function_decl : Flambda.function_declaration) ->
|
(fun _fun_var (function_decl : Flambda.function_declaration) ->
|
||||||
if function_decl.stub then None
|
if function_decl.stub then None
|
||||||
else
|
else
|
||||||
Some (Extract_projections.from_function_decl ~env
|
Some (Extract_projections.from_function_decl ~env
|
||||||
|
|
|
@ -40,6 +40,7 @@ module type S =
|
||||||
val for_all: (key -> 'a -> bool) -> 'a t -> bool
|
val for_all: (key -> 'a -> bool) -> 'a t -> bool
|
||||||
val exists: (key -> 'a -> bool) -> 'a t -> bool
|
val exists: (key -> 'a -> bool) -> 'a t -> bool
|
||||||
val filter: (key -> 'a -> bool) -> 'a t -> 'a t
|
val filter: (key -> 'a -> bool) -> 'a t -> 'a t
|
||||||
|
val filter_map: (key -> 'a -> 'b option) -> 'a t -> 'b t
|
||||||
val partition: (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
val partition: (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
||||||
val cardinal: 'a t -> int
|
val cardinal: 'a t -> int
|
||||||
val bindings: 'a t -> (key * 'a) list
|
val bindings: 'a t -> (key * 'a) list
|
||||||
|
@ -425,6 +426,18 @@ module Make(Ord: OrderedType) = struct
|
||||||
if pvd then if l==l' && r==r' then m else join l' v d r'
|
if pvd then if l==l' && r==r' then m else join l' v d r'
|
||||||
else concat l' r'
|
else concat l' r'
|
||||||
|
|
||||||
|
let rec filter_map f = function
|
||||||
|
Empty -> Empty
|
||||||
|
| Node {l; v; d; r} ->
|
||||||
|
(* call [f] in the expected left-to-right order *)
|
||||||
|
let l' = filter_map f l in
|
||||||
|
let fvd = f v d in
|
||||||
|
let r' = filter_map f r in
|
||||||
|
begin match fvd with
|
||||||
|
| Some d' -> join l' v d' r'
|
||||||
|
| None -> concat l' r'
|
||||||
|
end
|
||||||
|
|
||||||
let rec partition p = function
|
let rec partition p = function
|
||||||
Empty -> (Empty, Empty)
|
Empty -> (Empty, Empty)
|
||||||
| Node {l; v; d; r} ->
|
| Node {l; v; d; r} ->
|
||||||
|
|
|
@ -179,6 +179,26 @@ module type S =
|
||||||
@before 4.03 Physical equality was not ensured.
|
@before 4.03 Physical equality was not ensured.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
val filter_map: (key -> 'a -> 'b option) -> 'a t -> 'b t
|
||||||
|
(** [filter_map f m] applies the function [f] to every binding of
|
||||||
|
[m], and builds a map from the results. For each binding
|
||||||
|
[(k, v)] in the input map:
|
||||||
|
- if [f k v] is [None] then [k] is not in the result,
|
||||||
|
- if [f k v] is [Some v'] then the binding [(k, v')]
|
||||||
|
is in the output map.
|
||||||
|
|
||||||
|
For example, the following function on maps whose values are lists
|
||||||
|
{[
|
||||||
|
filter_map
|
||||||
|
(fun _k li -> match li with [] -> None | _::tl -> Some tl)
|
||||||
|
m
|
||||||
|
]}
|
||||||
|
drops all bindings of [m] whose value is an empty list, and pops
|
||||||
|
the first element of each value that is non-empty.
|
||||||
|
|
||||||
|
@since 4.11.0
|
||||||
|
*)
|
||||||
|
|
||||||
val partition: (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
val partition: (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
||||||
(** [partition p m] returns a pair of maps [(m1, m2)], where
|
(** [partition p m] returns a pair of maps [(m1, m2)], where
|
||||||
[m1] contains all the bindings of [s] that satisfy the
|
[m1] contains all the bindings of [s] that satisfy the
|
||||||
|
|
|
@ -152,6 +152,7 @@ module Map : sig
|
||||||
val for_all: f:(key -> 'a -> bool) -> 'a t -> bool
|
val for_all: f:(key -> 'a -> bool) -> 'a t -> bool
|
||||||
val exists: f:(key -> 'a -> bool) -> 'a t -> bool
|
val exists: f:(key -> 'a -> bool) -> 'a t -> bool
|
||||||
val filter: f:(key -> 'a -> bool) -> 'a t -> 'a t
|
val filter: f:(key -> 'a -> bool) -> 'a t -> 'a t
|
||||||
|
val filter_map: f:(key -> 'a -> 'b option) -> 'a t -> 'b t
|
||||||
val partition: f:(key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
val partition: f:(key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
||||||
val cardinal: 'a t -> int
|
val cardinal: 'a t -> int
|
||||||
val bindings: 'a t -> (key * 'a) list
|
val bindings: 'a t -> (key * 'a) list
|
||||||
|
@ -205,6 +206,7 @@ module Set : sig
|
||||||
val for_all : f:(elt -> bool) -> t -> bool
|
val for_all : f:(elt -> bool) -> t -> bool
|
||||||
val exists : f:(elt -> bool) -> t -> bool
|
val exists : f:(elt -> bool) -> t -> bool
|
||||||
val filter : f:(elt -> bool) -> t -> t
|
val filter : f:(elt -> bool) -> t -> t
|
||||||
|
val filter_map : f:(elt -> elt option) -> t -> t
|
||||||
val partition : f:(elt -> bool) -> t -> t * t
|
val partition : f:(elt -> bool) -> t -> t * t
|
||||||
val cardinal : t -> int
|
val cardinal : t -> int
|
||||||
val elements : t -> elt list
|
val elements : t -> elt list
|
||||||
|
|
|
@ -44,6 +44,7 @@ module type S =
|
||||||
val for_all: (elt -> bool) -> t -> bool
|
val for_all: (elt -> bool) -> t -> bool
|
||||||
val exists: (elt -> bool) -> t -> bool
|
val exists: (elt -> bool) -> t -> bool
|
||||||
val filter: (elt -> bool) -> t -> t
|
val filter: (elt -> bool) -> t -> t
|
||||||
|
val filter_map: (elt -> elt option) -> t -> t
|
||||||
val partition: (elt -> bool) -> t -> t * t
|
val partition: (elt -> bool) -> t -> t * t
|
||||||
val cardinal: t -> int
|
val cardinal: t -> int
|
||||||
val elements: t -> elt list
|
val elements: t -> elt list
|
||||||
|
@ -530,6 +531,27 @@ module Make(Ord: OrderedType) =
|
||||||
if l == l' && v == v' && r == r' then t
|
if l == l' && v == v' && r == r' then t
|
||||||
else try_join l' v' r'
|
else try_join l' v' r'
|
||||||
|
|
||||||
|
let try_concat t1 t2 =
|
||||||
|
match (t1, t2) with
|
||||||
|
(Empty, t) -> t
|
||||||
|
| (t, Empty) -> t
|
||||||
|
| (_, _) -> try_join t1 (min_elt t2) (remove_min_elt t2)
|
||||||
|
|
||||||
|
let rec filter_map f = function
|
||||||
|
| Empty -> Empty
|
||||||
|
| Node{l; v; r} as t ->
|
||||||
|
(* enforce left-to-right evaluation order *)
|
||||||
|
let l' = filter_map f l in
|
||||||
|
let v' = f v in
|
||||||
|
let r' = filter_map f r in
|
||||||
|
begin match v' with
|
||||||
|
| Some v' ->
|
||||||
|
if l == l' && v == v' && r == r' then t
|
||||||
|
else try_join l' v' r'
|
||||||
|
| None ->
|
||||||
|
try_concat l' r'
|
||||||
|
end
|
||||||
|
|
||||||
let of_sorted_list l =
|
let of_sorted_list l =
|
||||||
let rec sub n l =
|
let rec sub n l =
|
||||||
match n, l with
|
match n, l with
|
||||||
|
|
|
@ -154,6 +154,22 @@ module type S =
|
||||||
physically equal to [s]).
|
physically equal to [s]).
|
||||||
@before 4.03 Physical equality was not ensured.*)
|
@before 4.03 Physical equality was not ensured.*)
|
||||||
|
|
||||||
|
val filter_map: (elt -> elt option) -> t -> t
|
||||||
|
(** [filter_map f s] returns the set of all [v] such that
|
||||||
|
[f x = Some v] for some element [x] of [s].
|
||||||
|
|
||||||
|
For example,
|
||||||
|
{[filter_map (fun n -> if n mod 2 = 0 then Some (n / 2) else None) s]}
|
||||||
|
is the set of halves of the even elements of [s].
|
||||||
|
|
||||||
|
If no element of [s] is changed or dropped by [f] (if
|
||||||
|
[f x = Some x] for each element [x]), then
|
||||||
|
[s] is returned unchanged: the result of the function
|
||||||
|
is then physically equal to [s].
|
||||||
|
|
||||||
|
@since 4.11.0
|
||||||
|
*)
|
||||||
|
|
||||||
val partition: (elt -> bool) -> t -> t * t
|
val partition: (elt -> bool) -> t -> t * t
|
||||||
(** [partition p s] returns a pair of sets [(s1, s2)], where
|
(** [partition p s] returns a pair of sets [(s1, s2)], where
|
||||||
[s1] is the set of all the elements of [s] that satisfy the
|
[s1] is the set of all the elements of [s] that satisfy the
|
||||||
|
|
|
@ -75,6 +75,11 @@ let test x v s1 s2 =
|
||||||
(let p x y = x >= 3 && x <= 6 in
|
(let p x y = x >= 3 && x <= 6 in
|
||||||
M.bindings(M.filter p s1) = List.filter (uncurry p) (M.bindings s1));
|
M.bindings(M.filter p s1) = List.filter (uncurry p) (M.bindings s1));
|
||||||
|
|
||||||
|
checkbool "filter_map"
|
||||||
|
(let f x y = if x >= 3 && x <= 6 then Some (2 * x) else None in
|
||||||
|
let f_on_pair (x, y) = Option.map (fun v -> (x, v)) (f x y) in
|
||||||
|
M.bindings(M.filter_map f s1) = List.filter_map f_on_pair (M.bindings s1));
|
||||||
|
|
||||||
checkbool "partition"
|
checkbool "partition"
|
||||||
(let p x y = x >= 3 && x <= 6 in
|
(let p x y = x >= 3 && x <= 6 in
|
||||||
let (st,sf) = M.partition p s1
|
let (st,sf) = M.partition p s1
|
||||||
|
|
|
@ -89,6 +89,14 @@ let test x s1 s2 =
|
||||||
(let p x = x >= 3 && x <= 6 in
|
(let p x = x >= 3 && x <= 6 in
|
||||||
S.elements(S.filter p s1) = List.filter p (S.elements s1));
|
S.elements(S.filter p s1) = List.filter p (S.elements s1));
|
||||||
|
|
||||||
|
checkbool "filter_map"
|
||||||
|
(let f x = if x >= 3 && x <= 6 then Some (2 * x) else None in
|
||||||
|
S.elements(S.filter_map f s1) = List.filter_map f (S.elements s1));
|
||||||
|
|
||||||
|
checkbool "filter_map(==)"
|
||||||
|
(let f x = Some x in
|
||||||
|
S.filter_map f s1 == s1);
|
||||||
|
|
||||||
checkbool "partition"
|
checkbool "partition"
|
||||||
(let p x = x >= 3 && x <= 6 in
|
(let p x = x >= 3 && x <= 6 in
|
||||||
let (st,sf) = S.partition p s1
|
let (st,sf) = S.partition p s1
|
||||||
|
|
|
@ -321,6 +321,7 @@ module type MapT =
|
||||||
val for_all : (key -> 'a -> bool) -> 'a t -> bool
|
val for_all : (key -> 'a -> bool) -> 'a t -> bool
|
||||||
val exists : (key -> 'a -> bool) -> 'a t -> bool
|
val exists : (key -> 'a -> bool) -> 'a t -> bool
|
||||||
val filter : (key -> 'a -> bool) -> 'a t -> 'a t
|
val filter : (key -> 'a -> bool) -> 'a t -> 'a t
|
||||||
|
val filter_map : (key -> 'a -> 'b option) -> 'a t -> 'b t
|
||||||
val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
||||||
val cardinal : 'a t -> int
|
val cardinal : 'a t -> int
|
||||||
val bindings : 'a t -> (key * 'a) list
|
val bindings : 'a t -> (key * 'a) list
|
||||||
|
@ -372,6 +373,7 @@ module SSMap :
|
||||||
val for_all : (key -> 'a -> bool) -> 'a t -> bool
|
val for_all : (key -> 'a -> bool) -> 'a t -> bool
|
||||||
val exists : (key -> 'a -> bool) -> 'a t -> bool
|
val exists : (key -> 'a -> bool) -> 'a t -> bool
|
||||||
val filter : (key -> 'a -> bool) -> 'a t -> 'a t
|
val filter : (key -> 'a -> bool) -> 'a t -> 'a t
|
||||||
|
val filter_map : (key -> 'a -> 'b option) -> 'a t -> 'b t
|
||||||
val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
||||||
val cardinal : 'a t -> int
|
val cardinal : 'a t -> int
|
||||||
val bindings : 'a t -> (key * 'a) list
|
val bindings : 'a t -> (key * 'a) list
|
||||||
|
|
|
@ -298,6 +298,7 @@ module StringSet :
|
||||||
val for_all : (elt -> bool) -> t -> bool
|
val for_all : (elt -> bool) -> t -> bool
|
||||||
val exists : (elt -> bool) -> t -> bool
|
val exists : (elt -> bool) -> t -> bool
|
||||||
val filter : (elt -> bool) -> t -> t
|
val filter : (elt -> bool) -> t -> t
|
||||||
|
val filter_map : (elt -> elt option) -> t -> t
|
||||||
val partition : (elt -> bool) -> t -> t * t
|
val partition : (elt -> bool) -> t -> t * t
|
||||||
val cardinal : t -> int
|
val cardinal : t -> int
|
||||||
val elements : t -> elt list
|
val elements : t -> elt list
|
||||||
|
@ -343,6 +344,7 @@ module SSet :
|
||||||
val for_all : (elt -> bool) -> t -> bool
|
val for_all : (elt -> bool) -> t -> bool
|
||||||
val exists : (elt -> bool) -> t -> bool
|
val exists : (elt -> bool) -> t -> bool
|
||||||
val filter : (elt -> bool) -> t -> t
|
val filter : (elt -> bool) -> t -> t
|
||||||
|
val filter_map : (elt -> elt option) -> t -> t
|
||||||
val partition : (elt -> bool) -> t -> t * t
|
val partition : (elt -> bool) -> t -> t * t
|
||||||
val cardinal : t -> int
|
val cardinal : t -> int
|
||||||
val elements : t -> elt list
|
val elements : t -> elt list
|
||||||
|
@ -420,6 +422,7 @@ module A :
|
||||||
val for_all : (elt -> bool) -> t -> bool
|
val for_all : (elt -> bool) -> t -> bool
|
||||||
val exists : (elt -> bool) -> t -> bool
|
val exists : (elt -> bool) -> t -> bool
|
||||||
val filter : (elt -> bool) -> t -> t
|
val filter : (elt -> bool) -> t -> t
|
||||||
|
val filter_map : (elt -> elt option) -> t -> t
|
||||||
val partition : (elt -> bool) -> t -> t * t
|
val partition : (elt -> bool) -> t -> t * t
|
||||||
val cardinal : t -> int
|
val cardinal : t -> int
|
||||||
val elements : t -> elt list
|
val elements : t -> elt list
|
||||||
|
@ -532,6 +535,7 @@ module SInt :
|
||||||
val for_all : (elt -> bool) -> t -> bool
|
val for_all : (elt -> bool) -> t -> bool
|
||||||
val exists : (elt -> bool) -> t -> bool
|
val exists : (elt -> bool) -> t -> bool
|
||||||
val filter : (elt -> bool) -> t -> t
|
val filter : (elt -> bool) -> t -> t
|
||||||
|
val filter_map : (elt -> elt option) -> t -> t
|
||||||
val partition : (elt -> bool) -> t -> t * t
|
val partition : (elt -> bool) -> t -> t * t
|
||||||
val cardinal : t -> int
|
val cardinal : t -> int
|
||||||
val elements : t -> elt list
|
val elements : t -> elt list
|
||||||
|
|
|
@ -254,6 +254,7 @@ module MkT :
|
||||||
val for_all : (elt -> bool) -> t -> bool
|
val for_all : (elt -> bool) -> t -> bool
|
||||||
val exists : (elt -> bool) -> t -> bool
|
val exists : (elt -> bool) -> t -> bool
|
||||||
val filter : (elt -> bool) -> t -> t
|
val filter : (elt -> bool) -> t -> t
|
||||||
|
val filter_map : (elt -> elt option) -> t -> t
|
||||||
val partition : (elt -> bool) -> t -> t * t
|
val partition : (elt -> bool) -> t -> t * t
|
||||||
val cardinal : t -> int
|
val cardinal : t -> int
|
||||||
val elements : t -> elt list
|
val elements : t -> elt list
|
||||||
|
|
|
@ -34,6 +34,7 @@ module Core :
|
||||||
val for_all : (key -> 'a -> bool) -> 'a t -> bool
|
val for_all : (key -> 'a -> bool) -> 'a t -> bool
|
||||||
val exists : (key -> 'a -> bool) -> 'a t -> bool
|
val exists : (key -> 'a -> bool) -> 'a t -> bool
|
||||||
val filter : (key -> 'a -> bool) -> 'a t -> 'a t
|
val filter : (key -> 'a -> bool) -> 'a t -> 'a t
|
||||||
|
val filter_map : (key -> 'a -> 'b option) -> 'a t -> 'b t
|
||||||
val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
|
||||||
val cardinal : 'a t -> key
|
val cardinal : 'a t -> key
|
||||||
val bindings : 'a t -> (key * 'a) list
|
val bindings : 'a t -> (key * 'a) list
|
||||||
|
|
|
@ -43,7 +43,6 @@ module type Map = sig
|
||||||
with type key = T.t
|
with type key = T.t
|
||||||
and type 'a t = 'a Map.Make (T).t
|
and type 'a t = 'a Map.Make (T).t
|
||||||
|
|
||||||
val filter_map : 'a t -> f:(key -> 'a -> 'b option) -> 'b t
|
|
||||||
val of_list : (key * 'a) list -> 'a t
|
val of_list : (key * 'a) list -> 'a t
|
||||||
|
|
||||||
val disjoint_union :
|
val disjoint_union :
|
||||||
|
@ -102,12 +101,6 @@ end
|
||||||
module Make_map (T : Thing) = struct
|
module Make_map (T : Thing) = struct
|
||||||
include Map.Make (T)
|
include Map.Make (T)
|
||||||
|
|
||||||
let filter_map t ~f =
|
|
||||||
fold (fun id v map ->
|
|
||||||
match f id v with
|
|
||||||
| None -> map
|
|
||||||
| Some r -> add id r map) t empty
|
|
||||||
|
|
||||||
let of_list l =
|
let of_list l =
|
||||||
List.fold_left (fun map (id, v) -> add id v map) empty l
|
List.fold_left (fun map (id, v) -> add id v map) empty l
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ module type Map = sig
|
||||||
with type key = T.t
|
with type key = T.t
|
||||||
and type 'a t = 'a Map.Make (T).t
|
and type 'a t = 'a Map.Make (T).t
|
||||||
|
|
||||||
val filter_map : 'a t -> f:(key -> 'a -> 'b option) -> 'b t
|
|
||||||
val of_list : (key * 'a) list -> 'a t
|
val of_list : (key * 'a) list -> 'a t
|
||||||
|
|
||||||
(** [disjoint_union m1 m2] contains all bindings from [m1] and
|
(** [disjoint_union m1 m2] contains all bindings from [m1] and
|
||||||
|
|
Loading…
Reference in New Issue