From f140825e037714166501615864d5e5efd4557bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 24 Mar 2014 16:19:16 +0100 Subject: doc: Add maps to reference manual --- system/doc/reference_manual/maps.xml | 274 ++++++++++++++++++++++++++++++++ system/doc/reference_manual/part.xml | 1 + system/doc/reference_manual/xmlfiles.mk | 1 + 3 files changed, 276 insertions(+) create mode 100644 system/doc/reference_manual/maps.xml (limited to 'system/doc') diff --git a/system/doc/reference_manual/maps.xml b/system/doc/reference_manual/maps.xml new file mode 100644 index 0000000000..78808ce4a2 --- /dev/null +++ b/system/doc/reference_manual/maps.xml @@ -0,0 +1,274 @@ + + + + +
+ + 2014 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + Maps + + + + + maps.xml +
+ + +

Maps are considered experimental during OTP 17 and may be subject to change.

+

The documentation below describes it being possible to use arbitrary + expressions or variables as keys, this is NOT implemented in the current + version of Erlang/OTP.

+

Exceptions returns badarg instead of badmap, this will change in + the future releases.

+
+ +
+ Creating Maps +

+ Constructing a new map is done by letting an expression K be associated with + another expression V: +

+ #{ K => V } +

+ New maps may include multiple associations at construction by listing every + association: +

+ #{ K1 => V1, .., Kn => Vn } +

+ An empty map is constructed by not associating any terms with each other: +

+ #{} +

+ All keys and values in the map are terms. Any expression is first evaluated and + then the resulting terms are used as key and value respectively. +

+

+ Keys and values are separated by the => arrow and associations are + separated by ,. +

+ +

+ Examples: +

+ +M0 = #{}, % empty map +M1 = #{a => <<"hello">>}, % single association with literals +M2 = #{1 => 2, b => b}, % multiple associations with literals +M3 = #{k => {A,B}}, % single association with variables +M4 = #{{"w", 1} => f()}. % compound key associated with an evaluated expression +

+ where, A and B are any expressions and M0 through M4 + are the resulting map terms. +

+

+ If two matching keys are declared, the latter key will take precedence. +

+

+ Example: +

+ +
+1> #{1 => a, 1 => b}.
+#{1 => b }
+2> #{1.0 => a, 1 => b}.
+#{1 => b, 1.0 => a}
+
+

+ The order in which the expressions constructing the keys and their + associated values are evaluated is not defined. The syntactic order of + the key-value pairs in the construction is of no relevance, except in + the above mentioned case of two matching keys. +

+
+ +
+ Updating Maps +

+ Updating a map has similar syntax as constructing it. +

+

+ An expression defining the map to be updated is put in front of the expression + defining the keys to be updated and their respective values. +

+ M#{ K => V } +

+ where M is a term of type map and K and V are any expression. +

+

+ If key K does not match any existing key in the map, a new association + will be created from key K to value V. If key K matches + an existing key in map M its associated value will be replaced by the + new value V. In both cases the evaluated map expression will return a new map. +

+

+ If M is not of type map an exception of type badmap is thrown. +

+

+ To only update an existing value, the following syntax is used, +

+ M#{ K := V } +

+ where M is an term of type map, V is an expression and K + is an expression which evaluates to an existing key in M. +

+

+ If key K does not match any existing keys in map M an exception + of type badarg will be triggered at runtime. If a matching key K + is present in map M its associated value will be replaced by the new + value V and the evaluated map expression returns a new map. +

+

+ If M is not of type map an exception of type badmap is thrown. +

+

+ Examples: +

+ +M0 = #{}, +M1 = M0#{a => 0}, +M2 = M1#{a => 1, b => 2}, +M3 = M2#{"function" => fun() -> f() end}, +M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`. +

+ where M0 is any map. It follows that M1 .. M4 are maps as well. +

+

+ More Examples: +

+
+1> M = #{1 => a}.
+#{1 => a }
+2> M#{1.0 => b}.
+#{1 => a, 1.0 => b}.
+3> M#{1 := b}.
+#{1 => b}
+4> M#{1.0 := b}.
+** exception error: bad argument
+
+

+ As in construction, the order in which the key and value expressions + are evaluated is not defined. The + syntactic order of the key-value pairs in the update is of no + relevance, except in the case where two keys match, in which + case the latter value is used. +

+
+ +
+ Maps in Patterns +

+ Matching of key-value associations from maps is done in the following way: +

+ + #{ K := V } = M +

+ where M is any map. The key K has to be an expression with bound + variables or a literals, and V can be any pattern with either bound or + unbound variables. +

+

+ If the variable V is unbound, it will be bound to the value associated + with the key K, which has to exist in the map M. If the variable + V is bound, it has to match the value associated with K in M. +

+

Example:

+ +1> M = #{"tuple" => {1,2}}. +#{"tuple" => {1,2}} +2> #{"tuple" := {1,B}} = M. +#{"tuple" => {1,2}} +3> B. +2. +

+ This will bind variable B to integer 2. +

+

+ Similarly, multiple values from the map may be matched: +

+ #{ K1 := V1, .., Kn := Vn } = M +

+ where keys K1 .. Kn are any expressions with literals or bound variables. If all + keys exist in map M all variables in V1 .. Vn will be matched to the + associated values of their respective keys. +

+

+ If the matching conditions are not met, the match will fail, either with +

+ + + a badmatch exception, if used in the context of the matching operator + as in the example, + + + or resulting in the next clause being tested in function heads and + case expressions. + + +

+ Matching in maps only allows for := as delimiters of associations. + The order in which keys are declared in matching has no relevance. +

+

+ Duplicate keys are allowed in matching and will match each pattern associated + to the keys. +

+ #{ K := V1, K := V2 } = M +

+ Matching an expression against an empty map literal will match its type but + no variables will be bound: +

+ #{} = Expr +

+ This expression will match if the expression Expr is of type map, otherwise + it will fail with an exception badmatch. +

+
+ Matching syntax: Example with literals in function heads +

+ Matching of literals as keys are allowed in function heads. +

+ +%% only start if not_started +handle_call(start, From, #{ state := not_started } = S) -> +... + {reply, ok, S#{ state := start }}; + +%% only change if started +handle_call(change, From, #{ state := start } = S) -> +... + {reply, ok, S#{ state := changed }}; +
+
+
+ Maps in Guards +

+ Maps are allowed in guards as long as all sub-expressions are valid guard expressions. +

+

+ Two guard BIFs handles maps: +

+ + + is_map/1 + + + map_size/1 + + +
+
diff --git a/system/doc/reference_manual/part.xml b/system/doc/reference_manual/part.xml index b4f114c268..09f7a41d0a 100644 --- a/system/doc/reference_manual/part.xml +++ b/system/doc/reference_manual/part.xml @@ -35,6 +35,7 @@ + diff --git a/system/doc/reference_manual/xmlfiles.mk b/system/doc/reference_manual/xmlfiles.mk index 6886c8c7cf..181e6f8042 100644 --- a/system/doc/reference_manual/xmlfiles.mk +++ b/system/doc/reference_manual/xmlfiles.mk @@ -24,6 +24,7 @@ REF_MAN_CHAPTER_FILES = \ functions.xml \ expressions.xml \ macros.xml \ + maps.xml \ records.xml \ errors.xml \ processes.xml \ -- cgit v1.2.3