From 65bd8ade865eebe0d8a3c3210a4e2e9f334e229f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Sun, 10 Apr 2016 22:48:55 +0200 Subject: erts: Add BIF maps:take/2 --- lib/stdlib/src/maps.erl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'lib/stdlib') diff --git a/lib/stdlib/src/maps.erl b/lib/stdlib/src/maps.erl index a52928f77f..a8c2740617 100644 --- a/lib/stdlib/src/maps.erl +++ b/lib/stdlib/src/maps.erl @@ -28,7 +28,7 @@ %%% BIFs -export([get/2, find/2, from_list/1, is_key/2, keys/1, merge/2, - new/0, put/3, remove/2, + new/0, put/3, remove/2, take/2, to_list/1, update/3, values/1]). -spec get(Key,Map) -> Value when @@ -102,6 +102,13 @@ put(_,_,_) -> erlang:nif_error(undef). remove(_,_) -> erlang:nif_error(undef). +-spec take(Key,Map1) -> {Value,Map2} | error when + Key :: term(), + Map1 :: map(), + Value :: term(), + Map2 :: map(). + +take(_,_) -> erlang:nif_error(undef). -spec to_list(Map) -> [{Key,Value}] when Map :: map(), -- cgit v1.2.3 From f3c55529dbc9cb3bf8801bea9b64da78b9b73d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Sun, 10 Apr 2016 23:09:54 +0200 Subject: stdlib: Document maps:take/2 --- lib/stdlib/doc/src/maps.xml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'lib/stdlib') diff --git a/lib/stdlib/doc/src/maps.xml b/lib/stdlib/doc/src/maps.xml index 0f58f19421..97a7438890 100644 --- a/lib/stdlib/doc/src/maps.xml +++ b/lib/stdlib/doc/src/maps.xml @@ -300,6 +300,30 @@ false + + + + +

+ The function removes the Key, if it exists, and its associated value from + Map1 and returns a tuple with the removed Value and + the new map Map2 without key Key. + If the key does not exist error is returned. +

+

+ The call will fail with a {badmap,Map} exception if Map1 is not a map. +

+

Example:

+ +> Map = #{"a" => "hello", "b" => "world"}. +#{"a" => "hello", "b" => "world"} +> maps:take("a",Map). +{"hello",#{"b" => "world"}} +> maps:take("does not exist",Map). +error +
+
+ -- cgit v1.2.3 From 8d5bc31684f8b6969b5bfde70e25b153d4018f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 13 Apr 2016 19:06:05 +0200 Subject: stdlib: Add maps:update_with/3,4 Maps equivalent to dict:update/3,4 --- lib/stdlib/src/maps.erl | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) (limited to 'lib/stdlib') diff --git a/lib/stdlib/src/maps.erl b/lib/stdlib/src/maps.erl index a8c2740617..ba9ad4f549 100644 --- a/lib/stdlib/src/maps.erl +++ b/lib/stdlib/src/maps.erl @@ -20,12 +20,12 @@ -module(maps). --export([get/3,filter/2,fold/3, map/2, - size/1, +-export([get/3, filter/2,fold/3, + map/2, size/1, + update_with/3, update_with/4, without/2, with/2]). - -%%% BIFs +%% BIFs -export([get/2, find/2, from_list/1, is_key/2, keys/1, merge/2, new/0, put/3, remove/2, take/2, @@ -134,8 +134,40 @@ update(_,_,_) -> erlang:nif_error(undef). values(_) -> erlang:nif_error(undef). +%% End of BIFs + +-spec update_with(Key,Fun,Map1) -> Map2 when + Key :: term(), + Map1 :: map(), + Map2 :: map(), + Fun :: fun((Value1 :: term()) -> Value2 :: term()). + +update_with(Key,Fun,Map) when is_function(Fun,1), is_map(Map) -> + try maps:get(Key,Map) of + Val -> maps:update(Key,Fun(Val),Map) + catch + error:{badkey,_} -> + erlang:error({badkey,Key},[Key,Fun,Map]) + end; +update_with(Key,Fun,Map) -> + erlang:error(error_type(Map),[Key,Fun,Map]). + + +-spec update_with(Key,Fun,Init,Map1) -> Map2 when + Key :: term(), + Map1 :: Map1, + Map2 :: Map2, + Fun :: fun((Value1 :: term()) -> Value2 :: term()), + Init :: term(). + +update_with(Key,Fun,Init,Map) when is_function(Fun,1), is_map(Map) -> + case maps:find(Key,Map) of + {ok,Val} -> maps:update(Key,Fun(Val),Map); + error -> maps:put(Key,Init,Map) + end; +update_with(Key,Fun,Init,Map) -> + erlang:error(error_type(Map),[Key,Fun,Init,Map]). -%%% End of BIFs -spec get(Key, Map, Default) -> Value | Default when Key :: term(), -- cgit v1.2.3 From cb410cd727824f3dc0038759b16e29a31c4aba83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 13 Apr 2016 19:31:07 +0200 Subject: stdlib: Add tests for maps:update_with/3,4 --- lib/stdlib/test/maps_SUITE.erl | 56 +++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 17 deletions(-) (limited to 'lib/stdlib') diff --git a/lib/stdlib/test/maps_SUITE.erl b/lib/stdlib/test/maps_SUITE.erl index 8b3a8d7ae2..42e669a799 100644 --- a/lib/stdlib/test/maps_SUITE.erl +++ b/lib/stdlib/test/maps_SUITE.erl @@ -25,15 +25,10 @@ -include_lib("common_test/include/ct.hrl"). -%% Test server specific exports --export([all/0]). --export([suite/0]). --export([init_per_suite/1]). --export([end_per_suite/1]). --export([init_per_testcase/2]). --export([end_per_testcase/2]). - --export([t_get_3/1, t_filter_2/1, +-export([all/0, suite/0]). + +-export([t_update_with_3/1, t_update_with_4/1, + t_get_3/1, t_filter_2/1, t_fold_3/1,t_map_2/1,t_size_1/1, t_with_2/1,t_without_2/1]). @@ -41,29 +36,56 @@ %%-define(badarg(F,Args), {'EXIT', {badarg, [{maps,F,Args,_}|_]}}). %% silly broken hipe -define(badmap(V,F,_Args), {'EXIT', {{badmap,V}, [{maps,F,_,_}|_]}}). +-define(badkey(K,F,_Args), {'EXIT', {{badkey,K}, [{maps,F,_,_}|_]}}). -define(badarg(F,_Args), {'EXIT', {badarg, [{maps,F,_,_}|_]}}). suite() -> - [{ct_hooks, [ts_install_cth]}, + [{ct_hooks,[ts_install_cth]}, {timetrap,{minutes,1}}]. all() -> - [t_get_3,t_filter_2, + [t_update_with_3,t_update_with_4, + t_get_3,t_filter_2, t_fold_3,t_map_2,t_size_1, t_with_2,t_without_2]. -init_per_suite(Config) -> - Config. +t_update_with_3(Config) when is_list(Config) -> + V1 = value1, + V2 = <<"value2">>, + V3 = "value3", + Map = #{ key1 => V1, key2 => V2, "key3" => V3 }, + Fun = fun(V) -> [V,V,{V,V}] end, + + #{ key1 := [V1,V1,{V1,V1}] } = maps:update_with(key1,Fun,Map), + #{ key2 := [V2,V2,{V2,V2}] } = maps:update_with(key2,Fun,Map), + #{ "key3" := [V3,V3,{V3,V3}] } = maps:update_with("key3",Fun,Map), -end_per_suite(_Config) -> + %% error case + ?badmap(b,update_with,[[a,b],a,b]) = (catch maps:update_with([a,b],id(a),b)), + ?badarg(update_with,[[a,b],a,#{}]) = (catch maps:update_with([a,b],id(a),#{})), + ?badkey([a,b],update_with,[[a,b],Fun,#{}]) = (catch maps:update_with([a,b],Fun,#{})), ok. -init_per_testcase(_Case, Config) -> - Config. +t_update_with_4(Config) when is_list(Config) -> + V1 = value1, + V2 = <<"value2">>, + V3 = "value3", + Map = #{ key1 => V1, key2 => V2, "key3" => V3 }, + Fun = fun(V) -> [V,V,{V,V}] end, + Init = 3, + + #{ key1 := [V1,V1,{V1,V1}] } = maps:update_with(key1,Fun,Init,Map), + #{ key2 := [V2,V2,{V2,V2}] } = maps:update_with(key2,Fun,Init,Map), + #{ "key3" := [V3,V3,{V3,V3}] } = maps:update_with("key3",Fun,Init,Map), -end_per_testcase(_Case, _Config) -> + #{ key3 := Init } = maps:update_with(key3,Fun,Init,Map), + + %% error case + ?badmap(b,update_with,[[a,b],a,b]) = (catch maps:update_with([a,b],id(a),b)), + ?badarg(update_with,[[a,b],a,#{}]) = (catch maps:update_with([a,b],id(a),#{})), ok. + t_get_3(Config) when is_list(Config) -> Map = #{ key1 => value1, key2 => value2 }, DefaultValue = "Default value", -- cgit v1.2.3 From eeac08ca0ed6358a87f265f87a62bea8d0feb3b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Sat, 23 Apr 2016 00:17:04 +0200 Subject: stdlib: Document maps:update_with/3,4 --- lib/stdlib/doc/src/maps.xml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'lib/stdlib') diff --git a/lib/stdlib/doc/src/maps.xml b/lib/stdlib/doc/src/maps.xml index 97a7438890..bf45461e2b 100644 --- a/lib/stdlib/doc/src/maps.xml +++ b/lib/stdlib/doc/src/maps.xml @@ -381,6 +381,42 @@ error + + + + +

Update a value in a Map1 associated with Key by + calling Fun on the old value to get a new value. An exception + {badkey,Key} is generated if + Key is not present in the map.

+

Example:

+ +> Map = #{"counter" => 1}, + Fun = fun(V) -> V + 1 end, + maps:update_with("counter",Fun,Map). +#{"counter" => 2} +
+
+ + + + + +

Update a value in a Map1 associated with Key by + calling Fun on the old value to get a new value. + If Key is not present + in Map1 then Init will be associated with + Key. +

+

Example:

+ +> Map = #{"counter" => 1}, + Fun = fun(V) -> V + 1 end, + maps:update_with("new counter",Fun,42,Map). +#{"counter" => 1,"new counter" => 42} +
+
+ -- cgit v1.2.3