summaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
authorBjörn Gustavsson <bjorn@erlang.org>2020-01-27 10:50:10 +0100
committerBjörn Gustavsson <bjorn@erlang.org>2020-02-06 12:27:30 +0100
commit519e3916884eb3f1bb69917a0eea896c1b110c6c (patch)
tree6ba55ba641d9df0207fbe9a5d98e35c1365fcbd8 /system
parent4c980236dcc3e565d351f9d0d1980f599bf539bf (diff)
downloaderlang-519e3916884eb3f1bb69917a0eea896c1b110c6c.tar.gz
Update documentation for map and binary matching
Diffstat (limited to 'system')
-rw-r--r--system/doc/programming_examples/bit_syntax.xml32
-rw-r--r--system/doc/reference_manual/expressions.xml71
2 files changed, 82 insertions, 21 deletions
diff --git a/system/doc/programming_examples/bit_syntax.xml b/system/doc/programming_examples/bit_syntax.xml
index a64be0c007..870e07e41a 100644
--- a/system/doc/programming_examples/bit_syntax.xml
+++ b/system/doc/programming_examples/bit_syntax.xml
@@ -292,8 +292,9 @@ X:4/little-signed-integer-unit:8</code>
<p>When matching <c>Value</c>, value must be either a variable or
an integer, or a floating point literal. Expressions are not
allowed.</p>
- <p><c>Size</c> must be an integer literal, or a previously bound
- variable. The following is not allowed:</p>
+ <p><c>Size</c> must be a
+ <seealso marker="doc/reference_manual:expressions#guard_expressions">guard expression</seealso>, which can use literals and previously bound variables.
+ The following is not allowed:</p>
<code type="none"><![CDATA[
foo(N, <<X:N,T/binary>>) ->
{X,T}.]]></code>
@@ -304,6 +305,33 @@ foo(N, <<X:N,T/binary>>) ->
foo(N, Bin) ->
<<X:N,T/binary>> = Bin,
{X,T}.]]></code>
+ <note><p>Before OTP 23, <c>Size</c> was restricted to be an
+ integer or a variable bound to an integer.</p></note>
+
+ <section>
+ <title>Binding and Using a Size Variable</title>
+ <p>There is one exception to the rule that a variable that is
+ as size must be previously bound. It is possible to match and
+ bind a variable, and use it as a size within the the same
+ binary pattern. For example:</p>
+
+ <code type="none"><![CDATA[
+bar(<<Sz:8,Payload:Sz/binary-unit:8,Rest/binary>>) ->
+ {Payload,Rest}.]]></code>
+
+ <p>Here <c>Sz</c> is bound to the value in the first byte of
+ the binary. <c>Sz</c> is then used at the number of bytes
+ to match out as a binary.</p>
+
+ <p>Starting in OTP 23, the size can be a guard expression:</p>
+ <code type="none"><![CDATA[
+bar(<<Sz:8,Payload:((Sz-1)*8)/binary,Rest/binary>>) ->
+ {Payload,Rest}.]]></code>
+
+ <p>Here <c>Sz</c> is the combined size of the header and the
+ payload, so we will need to subtract one byte to get the size
+ of the payload.</p>
+ </section>
<section>
<title>Getting the Rest of the Binary or Bitstring</title>
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index baa1269470..d7d9acfb5e 100644
--- a/system/doc/reference_manual/expressions.xml
+++ b/system/doc/reference_manual/expressions.xml
@@ -944,7 +944,7 @@ M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code>
Here <c>M0</c> is any map. It follows that <c>M1 .. M4</c> are maps as well.
</p>
<p>
- More <em>Examples:</em>
+ <em>More examples:</em>
</p>
<pre>
1> <input>M = #{1 => a}.</input>
@@ -973,15 +973,20 @@ M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code>
<code>#{ K := V } = M</code>
<p>
- Here <c>M</c> is any map. The key <c>K</c> must be an expression with bound
- variables or literals. <c>V</c> can be any pattern with either bound or
- unbound variables.
+ Here <c>M</c> is any map. The key <c>K</c> must be a
+ <seealso marker="#guard_expressions">guard
+ expression</seealso>, with all variables already bound.
+ <c>V</c> can be any pattern with either bound or unbound
+ variables.
</p>
<p>
If the variable <c>V</c> is unbound, it becomes bound to the value associated
with the key <c>K</c>, which must exist in the map <c>M</c>. If the variable
<c>V</c> is bound, it must match the value associated with <c>K</c> in <c>M</c>.
</p>
+ <note><p>Before OTP 23, the expression defining the key
+ <c>K</c> was restricted to be either a single variable or a
+ literal.</p></note>
<p><em>Example:</em></p>
<pre>
1> <input>M = #{"tuple" => {1,2}}.</input>
@@ -998,9 +1003,12 @@ M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code>
</p>
<code>#{ K1 := V1, .., Kn := Vn } = M</code>
<p>
- Here keys <c>K1 .. Kn</c> are any expressions with literals or bound variables. If all
- keys exist in map <c>M</c>, all variables in <c>V1 .. Vn</c> is matched to the
- associated values of their respective keys.
+ Here keys <c>K1 .. Kn</c> are any expressions with
+ literals or bound variables. If all key expressions
+ evalute successfully and all keys exist in map
+ <c>M</c>, all variables in <c>V1 .. Vn</c> is
+ matched to the associated values of their respective
+ keys.
</p>
<p>
If the matching conditions are not met, the match fails, either with:
@@ -1034,6 +1042,9 @@ M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code>
This expression matches if the expression <c>Expr</c> is of type map, otherwise
it fails with an exception <c>badmatch</c>.
</p>
+ <p>Here the key to be retrieved is constructed from an expression:</p>
+ <code>#{{tag,length(List)} := V} = Map</code>
+ <p><c>List</c> must be an already bound variable.</p>
<section>
<title>Matching Syntax</title>
<p>
@@ -1057,7 +1068,7 @@ handle_call(change, From, #{ state := start } = S) ->
Maps are allowed in guards as long as all subexpressions are valid guard expressions.
</p>
<p>
- Two guard BIFs handle maps:
+ The following guard BIFs handle maps:
</p>
<list>
<item>
@@ -1065,6 +1076,10 @@ handle_call(change, From, #{ state := start } = S) ->
in the <c>erlang</c> module
</item>
<item>
+ <seealso marker="erts:erlang#map_get/2">map_get/2</seealso>
+ in the <c>erlang</c> module
+ </item>
+ <item>
<seealso marker="erts:erlang#map_size/1">map_size/1</seealso>
in the <c>erlang</c> module
</item>
@@ -1100,8 +1115,13 @@ Ei = Value |
<p>Used in a bit string construction, <c>Size</c> is an expression
that is to evaluate to an integer.</p>
- <p>Used in a bit string matching, <c>Size</c> must be an integer, or a
- variable bound to an integer.</p>
+ <p>Used in a bit string matching, <c>Size</c> must be a
+ <seealso marker="#guard_expressions">guard expression</seealso>
+ that evaluates to an integer. All variables in the guard expression
+ must be already bound.</p>
+
+ <note><p>Before OTP 23, <c>Size</c> was restricted to be an
+ integer or a variable bound to an integer.</p></note>
<p>The value of <c>Size</c> specifies the size of the segment in
units (see below). The default value depends on the type (see
@@ -1630,16 +1650,26 @@ end</pre>
by comma (,). The guard is true if all guard expressions
evaluate to <c>true</c>.</p>
<p><c>GuardExpr1,...,GuardExprN</c></p>
- <p>The set of valid <em>guard expressions</em> (sometimes called
- guard tests) is a subset of the set of valid Erlang expressions.
- The reason for restricting the set of valid expressions is that
- evaluation of a guard expression must be guaranteed to be free
- of side effects. Valid guard expressions are the following:</p>
+ </section>
+
+ <section>
+ <marker id="guard_expressions"></marker>
+ <title>Guard Expressions</title>
+ <p>The set of valid <em>guard expressions</em> is a subset of the
+ set of valid Erlang expressions. The reason for restricting the
+ set of valid expressions is that evaluation of a guard expression
+ must be guaranteed to be free of side effects. Valid guard
+ expressions are the following:</p>
<list type="bulleted">
- <item>The atom <c>true</c></item>
- <item>Other constants (terms and bound variables), all regarded
- as false</item>
- <item>Calls to the BIFs specified in table <c>Type Test BIFs</c></item>
+ <item>Variables</item>
+ <item>Constants (atoms, integer, floats, lists, tuples, records,
+ binaries, and maps)</item>
+ <item>Expressions that construct atoms, integer, floats, lists,
+ tuples, records, binaries, and maps</item>
+ <item>Expressions that update a map</item>
+ <item>The record epxressions <c>Expr#Name.Field</c> and <c>#Name.Field</c></item>
+ <item>Calls to the BIFs specified in tables <em>Type Test BIFs</em> and
+ <em>Other BIFs Allowed in Guard Expressions</em></item>
<item>Term comparisons</item>
<item>Arithmetic expressions</item>
<item>Boolean expressions</item>
@@ -1727,6 +1757,9 @@ end</pre>
<cell align="left" valign="middle"><c>length(List)</c></cell>
</row>
<row>
+ <cell align="left" valign="middle"><c>map_get(Key, Map)</c></cell>
+ </row>
+ <row>
<cell align="left" valign="middle"><c>map_size(Map)</c></cell>
</row>
<row>