Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:19
erlang
3272-Add-proplists-to_map-2-including-normaliza...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3272-Add-proplists-to_map-2-including-normalization.patch of Package erlang
From 0dc222a1cdbff5386212f262a7d1117cabb28f71 Mon Sep 17 00:00:00 2001 From: Maria-12648430 <maria-12648430@gmx.net> Date: Wed, 16 Dec 2020 17:47:58 +0100 Subject: [PATCH 2/2] Add proplists:to_map/2 including normalization --- lib/stdlib/doc/src/proplists.xml | 12 +++ lib/stdlib/src/proplists.erl | 44 ++++++++--- lib/stdlib/test/proplists_SUITE.erl | 112 +++++++++++++++++++--------- 3 files changed, 123 insertions(+), 45 deletions(-) diff --git a/lib/stdlib/doc/src/proplists.xml b/lib/stdlib/doc/src/proplists.xml index 05c02cc3be..6aed2d45e1 100644 --- a/lib/stdlib/doc/src/proplists.xml +++ b/lib/stdlib/doc/src/proplists.xml @@ -396,6 +396,18 @@ to_map([a, {b, 1}, {c, 2}, {c, 3}])</code> </desc> </func> + <func> + <name name="to_map" arity="2"/> + <fsummary></fsummary> + <desc> + <p>Converts the property list <c><anno>List</anno></c> to a map after + applying the normalizations given in <c><anno>Stages</anno></c>.</p> + <p>See also + <seealso marker="#normalize/2"><c>normalize/2</c></seealso>, + <seealso marker="#to_map/1"><c>to_map/1</c></seealso>.</p> + </desc> + </func> + <func> <name name="unfold" arity="1"/> <fsummary></fsummary> diff --git a/lib/stdlib/src/proplists.erl b/lib/stdlib/src/proplists.erl index b92982dae0..8f25229cdd 100644 --- a/lib/stdlib/src/proplists.erl +++ b/lib/stdlib/src/proplists.erl @@ -35,7 +35,8 @@ lookup_all/2, is_defined/2, get_value/2, get_value/3, get_all_values/2, append_values/2, get_bool/2, get_keys/1, delete/2, substitute_aliases/2, substitute_negations/2, - expand/2, normalize/2, split/2, from_map/1, to_map/1]). + expand/2, normalize/2, split/2, from_map/1, to_map/1, + to_map/2]). %% --------------------------------------------------------------------- @@ -607,14 +608,17 @@ flatten([]) -> Expansions :: [{Property :: property(), Expansion :: [term()]}], ListOut :: [term()]. -normalize(L, [{aliases, As} | Xs]) -> - normalize(substitute_aliases(As, L), Xs); -normalize(L, [{expand, Es} | Xs]) -> - normalize(expand(Es, L), Xs); -normalize(L, [{negations, Ns} | Xs]) -> - normalize(substitute_negations(Ns, L), Xs); -normalize(L, []) -> - compact(L). +normalize(L, Stages) -> + compact(apply_stages(L, Stages)). + +apply_stages(L, [{aliases, As} | Xs]) -> + apply_stages(substitute_aliases(As, L), Xs); +apply_stages(L, [{expand, Es} | Xs]) -> + apply_stages(expand(Es, L), Xs); +apply_stages(L, [{negations, Ns} | Xs]) -> + apply_stages(substitute_negations(Ns, L), Xs); +apply_stages(L, []) -> + L. %% --------------------------------------------------------------------- @@ -702,6 +706,8 @@ to_map(List) -> fun ({K, V}, M) -> M#{K => V}; + %% if tuples with arity /= 2 appear before atoms or + %% tuples with arity == 2, get_value/2,3 returns early (T, M) when 1 =< tuple_size(T) -> maps:remove(element(1, T), M); (K, M) when is_atom(K) -> @@ -713,6 +719,26 @@ to_map(List) -> List ). +%% @doc Converts the property list <code>List</code> to a map +%% after applying the normalizations given in <code>Stages</code>. +%% +%% @see normalize/2 +%% @see to_map/1 + +-spec to_map(List, Stages) -> Map when + List :: [term()], + Stages :: [Operation], + Operation :: {'aliases', Aliases} + | {'negations', Negations} + | {'expand', Expansions}, + Aliases :: [{Key, Key}], + Negations :: [{Key, Key}], + Expansions :: [{Property :: property(), Expansion :: [term()]}], + Map :: #{term() => term()}. + +to_map(List, Stages) -> + to_map(apply_stages(List, Stages)). + %% @doc Converts the map <code>Map</code> to a property list. -spec from_map(Map) -> List when diff --git a/lib/stdlib/test/proplists_SUITE.erl b/lib/stdlib/test/proplists_SUITE.erl index 64c5e60125..d0ebd2423e 100644 --- a/lib/stdlib/test/proplists_SUITE.erl +++ b/lib/stdlib/test/proplists_SUITE.erl @@ -23,7 +23,8 @@ -export([all/0, suite/0,groups/0, init_per_suite/1, end_per_suite/1, init_per_group/2, end_per_group/2, init_per_testcase/2, end_per_testcase/2, - examples/1, map_conversion/1]). + examples/1, map_conversion/1, map_conversion_normalize/1, + pm_fold_test/1]). init_per_testcase(_Case, Config) -> Config. @@ -36,7 +37,7 @@ suite() -> {timetrap,{minutes,5}}]. all() -> - [examples, map_conversion]. + [examples, map_conversion, map_conversion_normalize, pm_fold_test]. groups() -> []. @@ -103,39 +104,78 @@ map_conversion(_Config) -> %% map yields the same results as proplists:get_value/3 on the %% original proplist, ie they either all return the same `Value', %% or they all return the `Default' given as respective third argument. - Default1 = make_ref(), - Default2 = make_ref(), - Default3 = make_ref(), - InList=[a, b, {a, 1}, {}, {a}, {a, 1, 2}, "foo"], - lists:foreach( - fun (L1) -> - LKs = proplists:get_keys(L1), - M = proplists:to_map(L1), - L2 = proplists:from_map(M), - [] = maps:keys(M) -- LKs, - [] = proplists:get_keys(L2) -- LKs, - lists:foreach( - fun (K) -> - case - { - maps:get(K, M, Default1), - proplists:get_value(K, L1, Default2), - proplists:get_value(K, L2, Default3) - } - of - {V, V, V} -> true; - {Default1, Default2, Default3} -> true - end - end, - LKs - ) + Default = make_ref(), + InList=[a, b, {a, 1}, {}, {a}, {a, 1, 2}, {c, 1, 2}, "foo"], + Fun = fun (L1, Acc) -> + LKs = proplists:get_keys(L1), + M = proplists:to_map(L1), + L2 = proplists:from_map(M), + true = lists:sort(maps:keys(M)) =:= lists:sort(proplists:get_keys(L2)), + lists:foreach( + fun (K) -> + case + { + maps:get(K, M, Default), + proplists:get_value(K, L1, Default), + proplists:get_value(K, L2, Default) + } + of + {Default, Default, Default} -> ok; + {V, V, V} -> ok + end + end, + LKs + ), + Acc + end, + _ = pm_fold(Fun, undefined, InList), + ok. + +map_conversion_normalize(_Config) -> + Stages = [ + {aliases, [{a, alias_a}]}, + {negations, [{no_b, b}]}, + {expand, [{c, [d]}]} + ], + + M1 = proplists:to_map([], Stages), + true = M1 =:= #{}, + true = M1 =:= proplists:to_map(proplists:normalize([], Stages)), + + List = [a, no_b, c], + M2 = proplists:to_map(List, Stages), + true = M2 =:= #{alias_a => true, b => false, d => true}, + true = M2 =:= proplists:to_map(proplists:normalize(List, Stages)), + + ok. + +pm_fold(_, _, []) -> + []; +pm_fold(Fun, Acc0, L) -> + pm_fold(Fun, Acc0, L, []). + +pm_fold(Fun, Acc, [], Mut) -> + Fun(Mut, Acc); +pm_fold(Fun, Acc, L, Mut) -> + lists:foldl( + fun + (X, AccIn) -> pm_fold(Fun, AccIn, lists:delete(X, L), [X|Mut]) end, - [[A, B, C, D, E, F, G] || A <- InList, - B <- InList -- [A], - C <- InList -- [A, B], - D <- InList -- [A, B, C], - E <- InList -- [A, B, C, D], - F <- InList -- [A, B, C, D, E], - G <- InList -- [A, B, C, D, E, F]] - ), + Acc, + L + ). + +pm_fold_test(_Config) -> + Fun = fun (M, A) -> [M|A] end, + + [] = pm_fold(Fun, [], []), + + [[1]] = lists:sort(pm_fold(Fun, [], [1])), + + Exp1 = lists:sort([[1, 2], [2, 1]]), + Exp1 = lists:sort(pm_fold(Fun, [], [1, 2])), + + Exp2 = lists:sort([[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]), + Exp2 = lists:sort(pm_fold(Fun, [], [1, 2, 3])), + ok. -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor