diff options
author | Björn Gustavsson <bjorn@erlang.org> | 2020-01-27 10:50:10 +0100 |
---|---|---|
committer | Björn Gustavsson <bjorn@erlang.org> | 2020-02-06 12:27:30 +0100 |
commit | 519e3916884eb3f1bb69917a0eea896c1b110c6c (patch) | |
tree | 6ba55ba641d9df0207fbe9a5d98e35c1365fcbd8 /system | |
parent | 4c980236dcc3e565d351f9d0d1980f599bf539bf (diff) | |
download | erlang-519e3916884eb3f1bb69917a0eea896c1b110c6c.tar.gz |
Update documentation for map and binary matching
Diffstat (limited to 'system')
-rw-r--r-- | system/doc/programming_examples/bit_syntax.xml | 32 | ||||
-rw-r--r-- | system/doc/reference_manual/expressions.xml | 71 |
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> |