From 274e5b47bfbc86e8b9591134f28da9ef68f87221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 14 May 2014 17:07:38 +0200 Subject: doc: Move Maps reference documentation to expressions --- system/doc/reference_manual/expressions.xml | 238 ++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) (limited to 'system/doc/reference_manual/expressions.xml') diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml index 37208710fe..0ca425da86 100644 --- a/system/doc/reference_manual/expressions.xml +++ b/system/doc/reference_manual/expressions.xml @@ -791,6 +791,244 @@ Expr1 -- Expr2 long lists.

+
+ Map Expressions +
+ 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 + + +
+
+
Bit Syntax Expressions -- cgit v1.2.3