Permalink
Browse files

Update maps EEP to use match instead of equal

We have updated notes for the => operator to make it clear
it will *match* keys. We have also updated the functions
in the maps module to mention *match* semantics (for example,
`maps:from_list/1`).

We have also removed examples that use `lists:key*` functions
since those use equal. Notes regarding ordering have not
been affected by this commit.
  • Loading branch information...
1 parent bf2d098 commit 81fc8d43a88dae3e617d7883ab9fa36ea20723cd @josevalim josevalim committed with psyeugenic Jan 21, 2014
Showing with 19 additions and 32 deletions.
  1. +19 −32 eeps/eep-0043.md
View
@@ -73,7 +73,7 @@ Specification
=============
A map `M` consists of a number of *associations* and keeps an association
-from key terms `K1..Kn` to value terms `V1..Vn` where no two keys are *equal*.
+from key terms `K1..Kn` to value terms `V1..Vn` where no two keys *match*.
Any term, compounded or otherwise, is a viable key or value. Terms of type Map
are recognized by guard tests `erlang:is_map/1`. There are no operators
acting on maps. Within maps there are two infix operators. An association
@@ -89,8 +89,6 @@ The *size* of a map is the number of associations in its set.
An *association* is a key-value pair of key *K* to value *V* in a Map.
-Two keys, `K1` and `K2` are *equal* if, `true = K1 == K2`.
-
Two keys, `K1` and `K2` are *matching* if, `true = K1 =:= K2`.
Syntax
@@ -132,19 +130,19 @@ Examples:
where, `A` and `B` are any expressions and `M0` through `M4` are the resulting
map terms.
-If two equal keys are declared, the latter key will take precedent.
+If two matching keys are declared, the latter key will take precedent.
Example:
1> #{ 1 => a, 1 => b }.
#{ 1 => b }
2> #{ 1.0 => a, 1 => b }.
- #{ 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 keys comparing equal.
+the above mentioned case of two matching keys.
A simple BNF grammar for the construction follows:
@@ -167,10 +165,9 @@ defining the keys to be updated and their respective values.
where `M` is an term of type map and `K` and `V` are any expression.
-If key `K` does not *equal* any existing key in the map, a new association
-will be created from key `K` to value `V`. If key `K` is *equal* to an existing
-key in map `M` its associated value will be replaced by the new value `V` *and*
-the new key `K` will replace the old key if the key does not *match*. In both
+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.
@@ -202,11 +199,11 @@ where `M0` is any map. It follows that `M1 .. M4` are maps as well.
More Examples:
- 1> M = #{ 1 => a },
+ 1> M = #{ 1 => a }.
#{ 1 => a }
2> M#{ 1.0 => b }.
- #{ 1.0 => b }.
+ #{ 1 => a, 1.0 => b }.
3> M#{ 1 := b }.
#{ 1 => b }
@@ -218,7 +215,7 @@ More Examples:
As in construction, the order in which the key and value expressions
are evaluated are not defined. The
syntactic order of the key-value pairs in the update is of no
-relevance, except in the case where two keys compare equal, in which
+relevance, except in the case where two keys match, in which
case the latter value is used.
A simple BNF grammar for map updates follows:
@@ -244,8 +241,8 @@ For accessing single values in maps, let us use an de-association:
Where `M` is a Map and `K` is any term.
-If key `K` is *equal* to an existing key in map `M` the associated value
-will be bound to `V`. If key `K` does not *equal* to any existing key in
+If key `K` *matches* to an existing key in map `M` the associated value
+will be bound to `V`. If key `K` does not *match* to any existing key in
map `M` an exception `badarg` will occur in runtime.
@@ -484,12 +481,9 @@ Richard O'Keefes frames proposal.
Syntax equivalence: `M#{ K }`.
Returns the value `V` associated with key `K` if map `M` contains a key
- that *equals* `K`. If no value is associated with key `K` then the call will
+ that *matches* `K`. If no value is associated with key `K` then the call will
fail with an exception.
- Same as,`begin {value,{_,V}} = lists:keysearch(K, 1, maps:to_list(M)), V end`,
- except for errors.
-
##### `maps:keys(M :: map()) -> [K1, .., Kn].`
Syntax equivalence: `[K || K := _ <- M]`.
@@ -507,8 +501,6 @@ Richard O'Keefes frames proposal.
contains key `K`. If no value is associated with key `K` then the function
will return `error`.
- Same as, `case lists:keysearch(K, 1, maps:to_list(M)) of {value,{_,V}} -> {ok,V}; false -> error end`.
-
##### `maps:foldl(F :: fun((K :: term(), V :: term(), In :: term()) -> Out :: term()), A :: term(), M :: map()) -> Result :: term().`
Syntax equivalence: *none*
@@ -546,9 +538,7 @@ Richard O'Keefes frames proposal.
Syntax equivalence: `try #{ K := _ } = M, true catch error:{badmatch, _} -> false end`.
- Returns `true` if map `M` contains key `K`, otherwise it returns `false`.
-
- Same as, `lists:keymember(K, 1, maps:to_list(M))`.
+ Returns `true` if map `M` contains a key that *matches* `K`.
##### `maps:map(F :: function(), M0 :: map()) -> M1 :: map().`
@@ -583,9 +573,8 @@ Richard O'Keefes frames proposal.
Syntax equivalence: `M0#{ K => V }`.
Associates key `K` with value `V` and inserts the association into map `M0`.
- If a key exists that *equals* `K`, the old associated value is
- replaced by value `V`. If key `K` does not *match* but *equals* the
- old key is also replaced by key `K`.
+ If a key exists that *matches* `K`, the old associated value is
+ replaced by value `V`.
The function returns a new map `M1` containing the new association.
Same as, `maps:from_list(maps:to_list(M0) ++ [{K,V}])`.
@@ -629,11 +618,9 @@ Richard O'Keefes frames proposal.
Syntax equivalence: *none*
- Merges two maps into a single map. If two *equal* keys exists in both maps the
+ Merges two maps into a single map. If two *matching* keys exists in both maps the
value in map `M0` will be superseded by the value in map `M1`.
- Same as, `maps:from_list(lists:keymerge(1,maps:to_list(M0),maps:to_list(M1)))`.
-
Equality and Ordering
---------------------
@@ -763,7 +750,7 @@ an exception, `exception error: no match of right hand side value ...`.
** exception error: no match of right hand side value #{ a => 1 }
Similarly, if a value for a requested key in the LHS pattern
-is not equal to the keys associated value in the RHS map
+does not match the keys associated value in the RHS map
the match will produce an exception.
1> #{ a := 10 } = #{ a => 1 }.
@@ -1327,7 +1314,7 @@ Semantics and API-functions
Perhaps the most sane `maps:from_list/1` semantics would be to have the key-value
significance order in left to right, meaning the first association is used and
-the latter values with equal keys are ignored.
+the latter values with matching keys are ignored.
This differs from the `dict:from_list/1` behavior.

0 comments on commit 81fc8d4

Please sign in to comment.