diff options
Diffstat (limited to 'erts/doc/src/match_spec.xml')
-rw-r--r-- | erts/doc/src/match_spec.xml | 966 |
1 files changed, 569 insertions, 397 deletions
diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml index 7be3d15de6..2a14f1e47b 100644 --- a/erts/doc/src/match_spec.xml +++ b/erts/doc/src/match_spec.xml @@ -22,7 +22,7 @@ </legalnotice> - <title>Match specifications in Erlang</title> + <title>Match Specifications in Erlang</title> <prepared>Patrik Nyblom</prepared> <responsible></responsible> <docno></docno> @@ -32,43 +32,54 @@ <rev>PA1</rev> <file>match_spec.xml</file> </header> - <p>A "match specification" (match_spec) is an Erlang term describing a - small "program" that will try to match something. It can be used + <p>A "match specification" (<c>match_spec</c>) is an Erlang term describing a + small "program" that tries to match something. It can be used to either control tracing with <seealso marker="erlang#trace_pattern/3">erlang:trace_pattern/3</seealso> or to search for objects in an ETS table with for example <seealso marker="stdlib:ets#select/2">ets:select/2</seealso>. - The match_spec in many ways works like a small function in Erlang, but is - interpreted/compiled by the Erlang runtime system to something much more - efficient than calling an Erlang function. The match_spec is also + The match specification in many ways works like a small function in Erlang, + but is interpreted/compiled by the Erlang runtime system to something much more + efficient than calling an Erlang function. The match specification is also very limited compared to the expressiveness of real Erlang functions.</p> - <p>The most notable difference between a match_spec and an Erlang fun is - of course the syntax. Match specifications are Erlang terms, not - Erlang code. A match_spec also has a somewhat strange concept of - exceptions. An exception (e.g., <c><![CDATA[badarg]]></c>) in the <c><![CDATA[MatchCondition]]></c> - part, - which resembles an Erlang guard, will generate immediate failure, - while an exception in the <c><![CDATA[MatchBody]]></c> part, which resembles the body of an - Erlang function, is implicitly caught and results in the single atom - <c><![CDATA['EXIT']]></c>. - </p> + <p>The most notable difference between a match specification and an Erlang + fun is the syntax. Match specifications are Erlang terms, not Erlang code. + Also, a match specification has a strange concept of exceptions:</p> + + <list type="bulleted"> + <item> + <p>An exception (such as <c><![CDATA[badarg]]></c>) in the + <c><![CDATA[MatchCondition]]></c> part, which resembles an Erlang guard, + generates immediate failure.</p> + </item> + <item> + <p>An exception in the <c><![CDATA[MatchBody]]></c> part, which resembles + the body of an Erlang function, is implicitly caught and results in the + single atom <c><![CDATA['EXIT']]></c>.</p> + </item> + </list> <section> <title>Grammar</title> - <p>A match_spec used in tracing can be described in this <em>informal</em> grammar:</p> + <p>A match specification used in tracing can be described in the following + <em>informal</em> grammar:</p> + <list type="bulleted"> <item>MatchExpression ::= [ MatchFunction, ... ] </item> <item>MatchFunction ::= { MatchHead, MatchConditions, MatchBody } </item> - <item>MatchHead ::= MatchVariable | <c><![CDATA['_']]></c> | [ MatchHeadPart, ... ] + <item>MatchHead ::= MatchVariable | <c><![CDATA['_']]></c> | + [ MatchHeadPart, ... ] + </item> + <item>MatchHeadPart ::= term() | MatchVariable | <c><![CDATA['_']]></c> </item> - <item>MatchHeadPart ::= term() | MatchVariable | <c><![CDATA['_']]></c></item> <item>MatchVariable ::= '$<number>' </item> - <item>MatchConditions ::= [ MatchCondition, ...] | <c><![CDATA[[]]]></c></item> - <item>MatchCondition ::= { GuardFunction } | - { GuardFunction, ConditionExpression, ... } + <item>MatchConditions ::= [ MatchCondition, ...] | <c><![CDATA[[]]]></c> + </item> + <item>MatchCondition ::= { GuardFunction } | { GuardFunction, + ConditionExpression, ... } </item> <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | @@ -79,58 +90,77 @@ <c><![CDATA[is_function]]></c> | <c><![CDATA[is_record]]></c> | <c><![CDATA[is_seq_trace]]></c> | <c><![CDATA['and']]></c> | <c><![CDATA['or']]></c> | <c><![CDATA['not']]></c> | - <c><![CDATA['xor']]></c> | <c><![CDATA[andalso]]></c> | - <c><![CDATA[orelse]]></c></item> + <c><![CDATA['xor']]></c> | <c><![CDATA['andalso']]></c> | + <c><![CDATA['orelse']]></c> + </item> <item>ConditionExpression ::= ExprMatchVariable | { GuardFunction } | - { GuardFunction, ConditionExpression, ... } | TermConstruct + { GuardFunction, ConditionExpression, ... } | TermConstruct + </item> + <item>ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | + <c><![CDATA['$_']]></c> | <c><![CDATA['$$']]></c> </item> - <item>ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | - <c><![CDATA['$_']]></c> | <c><![CDATA['$$']]></c></item> <item>TermConstruct = {{}} | {{ ConditionExpression, ... }} | <c><![CDATA[[]]]></c> | [ConditionExpression, ...] | <c><![CDATA[#{}]]></c> | #{term() => ConditionExpression, ...} | - NonCompositeTerm | Constant</item> - <item>NonCompositeTerm ::= term() (not list or tuple or map)</item> + NonCompositeTerm | Constant + </item> + <item>NonCompositeTerm ::= term() (not list or tuple or map) + </item> <item>Constant ::= {<c><![CDATA[const]]></c>, term()} </item> <item>GuardFunction ::= BoolFunction | <c><![CDATA[abs]]></c> | - <c><![CDATA[element]]></c> | <c><![CDATA[hd]]></c> | <c><![CDATA[length]]></c> | <c><![CDATA[node]]></c> | - <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> | <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> | - <c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> | <c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> | - <c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> | <c><![CDATA['bor']]></c> | <c><![CDATA['bxor']]></c> | - <c><![CDATA['bnot']]></c> | <c><![CDATA['bsl']]></c> | <c><![CDATA['bsr']]></c> | <c><![CDATA['>']]></c> | - <c><![CDATA['>=']]></c> | <c><![CDATA['<']]></c> | <c><![CDATA['=<']]></c> | <c><![CDATA['=:=']]></c> | - <c><![CDATA['==']]></c> | <c><![CDATA['=/=']]></c> | <c><![CDATA['/=']]></c> | <c><![CDATA[self]]></c> | - <c><![CDATA[get_tcw]]></c></item> + <c><![CDATA[element]]></c> | <c><![CDATA[hd]]></c> | + <c><![CDATA[length]]></c> | <c><![CDATA[node]]></c> | + <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> | + <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> | + <c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> | + <c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> | + <c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> | + <c><![CDATA['bor']]></c> | <c><![CDATA['bxor']]></c> | + <c><![CDATA['bnot']]></c> | <c><![CDATA['bsl']]></c> | + <c><![CDATA['bsr']]></c> | <c><![CDATA['>']]></c> | + <c><![CDATA['>=']]></c> | <c><![CDATA['<']]></c> | + <c><![CDATA['=<']]></c> | <c><![CDATA['=:=']]></c> | + <c><![CDATA['==']]></c> | <c><![CDATA['=/=']]></c> | + <c><![CDATA['/=']]></c> | <c><![CDATA[self]]></c> | + <c><![CDATA[get_tcw]]></c> + </item> <item>MatchBody ::= [ ActionTerm ] </item> <item>ActionTerm ::= ConditionExpression | ActionCall </item> - <item>ActionCall ::= {ActionFunction} | - {ActionFunction, ActionTerm, ...} + <item>ActionCall ::= {ActionFunction} | {ActionFunction, ActionTerm, ...} </item> <item>ActionFunction ::= <c><![CDATA[set_seq_token]]></c> | - <c><![CDATA[get_seq_token]]></c> | <c><![CDATA[message]]></c> | - <c><![CDATA[return_trace]]></c> | <c><![CDATA[exception_trace]]></c> | <c><![CDATA[process_dump]]></c> | - <c><![CDATA[enable_trace]]></c> | <c><![CDATA[disable_trace]]></c> | <c><![CDATA[trace]]></c> | - <c><![CDATA[display]]></c> | <c><![CDATA[caller]]></c> | <c><![CDATA[set_tcw]]></c> | - <c><![CDATA[silent]]></c></item> + <c><![CDATA[get_seq_token]]></c> | <c><![CDATA[message]]></c> | + <c><![CDATA[return_trace]]></c> | <c><![CDATA[exception_trace]]></c> | + <c><![CDATA[process_dump]]></c> | <c><![CDATA[enable_trace]]></c> | + <c><![CDATA[disable_trace]]></c> | <c><![CDATA[trace]]></c> | + <c><![CDATA[display]]></c> | <c><![CDATA[caller]]></c> | + <c><![CDATA[set_tcw]]></c> | <c><![CDATA[silent]]></c> + </item> </list> - <p>A match_spec used in ets can be described in this <em>informal</em> grammar:</p> + <p>A match specification used in + <seealso marker="stdlib:ets"><c>ets(3)</c></seealso> + can be described in the following <em>informal</em> grammar:</p> + <list type="bulleted"> <item>MatchExpression ::= [ MatchFunction, ... ] </item> <item>MatchFunction ::= { MatchHead, MatchConditions, MatchBody } </item> - <item>MatchHead ::= MatchVariable | <c><![CDATA['_']]></c> | { MatchHeadPart, ... } + <item>MatchHead ::= MatchVariable | <c><![CDATA['_']]></c> | + { MatchHeadPart, ... } + </item> + <item>MatchHeadPart ::= term() | MatchVariable | <c><![CDATA['_']]></c> </item> - <item>MatchHeadPart ::= term() | MatchVariable | <c><![CDATA['_']]></c></item> <item>MatchVariable ::= '$<number>' </item> - <item>MatchConditions ::= [ MatchCondition, ...] | <c><![CDATA[[]]]></c></item> + <item>MatchConditions ::= [ MatchCondition, ...] | <c><![CDATA[[]]]></c> + </item> <item>MatchCondition ::= { GuardFunction } | - { GuardFunction, ConditionExpression, ... } + { GuardFunction, ConditionExpression, ... } </item> <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | @@ -141,243 +171,322 @@ <c><![CDATA[is_function]]></c> | <c><![CDATA[is_record]]></c> | <c><![CDATA[is_seq_trace]]></c> | <c><![CDATA['and']]></c> | <c><![CDATA['or']]></c> | <c><![CDATA['not']]></c> | - <c><![CDATA['xor']]></c> | <c><![CDATA[andalso]]></c> | - <c><![CDATA[orelse]]></c></item> + <c><![CDATA['xor']]></c> | <c><![CDATA['andalso']]></c> | + <c><![CDATA['orelse']]></c> + </item> <item>ConditionExpression ::= ExprMatchVariable | { GuardFunction } | - { GuardFunction, ConditionExpression, ... } | TermConstruct + { GuardFunction, ConditionExpression, ... } | TermConstruct </item> <item>ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | - <c><![CDATA['$_']]></c> | <c><![CDATA['$$']]></c></item> + <c><![CDATA['$_']]></c> | <c><![CDATA['$$']]></c> + </item> <item>TermConstruct = {{}} | {{ ConditionExpression, ... }} | <c><![CDATA[[]]]></c> | [ConditionExpression, ...] | #{} | - #{term() => ConditionExpression, ...} | NonCompositeTerm | - Constant</item> - <item>NonCompositeTerm ::= term() (not list or tuple or map)</item> + #{term() => ConditionExpression, ...} | NonCompositeTerm | Constant + </item> + <item>NonCompositeTerm ::= term() (not list or tuple or map) + </item> <item>Constant ::= {<c><![CDATA[const]]></c>, term()} </item> <item>GuardFunction ::= BoolFunction | <c><![CDATA[abs]]></c> | - <c><![CDATA[element]]></c> | <c><![CDATA[hd]]></c> | <c><![CDATA[length]]></c> | <c><![CDATA[node]]></c> | - <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> | <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> | - <c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> | <c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> | - <c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> | <c><![CDATA['bor']]></c> | <c><![CDATA['bxor']]></c> | - <c><![CDATA['bnot']]></c> | <c><![CDATA['bsl']]></c> | <c><![CDATA['bsr']]></c> | <c><![CDATA['>']]></c> | - <c><![CDATA['>=']]></c> | <c><![CDATA['<']]></c> | <c><![CDATA['=<']]></c> | <c><![CDATA['=:=']]></c> | - <c><![CDATA['==']]></c> | <c><![CDATA['=/=']]></c> | <c><![CDATA['/=']]></c> | <c><![CDATA[self]]></c> | - <c><![CDATA[get_tcw]]></c></item> - <item>MatchBody ::= [ ConditionExpression, ... ]</item> + <c><![CDATA[element]]></c> | <c><![CDATA[hd]]></c> | + <c><![CDATA[length]]></c> | <c><![CDATA[node]]></c> | + <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> | + <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> | + <c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> | + <c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> | + <c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> | + <c><![CDATA['bor']]></c> | <c><![CDATA['bxor']]></c> | + <c><![CDATA['bnot']]></c> | <c><![CDATA['bsl']]></c> | + <c><![CDATA['bsr']]></c> | <c><![CDATA['>']]></c> | + <c><![CDATA['>=']]></c> | <c><![CDATA['<']]></c> | + <c><![CDATA['=<']]></c> | <c><![CDATA['=:=']]></c> | + <c><![CDATA['==']]></c> | <c><![CDATA['=/=']]></c> | + <c><![CDATA['/=']]></c> | <c><![CDATA[self]]></c> | + <c><![CDATA[get_tcw]]></c> + </item> + <item>MatchBody ::= [ ConditionExpression, ... ] + </item> </list> </section> <section> - <title>Function descriptions</title> - + <title>Function Descriptions</title> <section> - <title>Functions allowed in all types of match specifications</title> - <p>The different functions allowed in <c><![CDATA[match_spec]]></c> work like this: - </p> - <p><em>is_atom, is_float, is_integer, is_list, is_number, is_pid, is_port, - is_reference, is_tuple, is_map, is_binary, is_function:</em> Like the - corresponding guard tests in Erlang, return <c><![CDATA[true]]></c> or - <c><![CDATA[false]]></c>.</p> - <p><em>is_record: </em>Takes an additional parameter, which SHALL - be the result of <c><![CDATA[record_info(size, <record_type>)]]></c>, - like in <c><![CDATA[{is_record, '$1', rectype, record_info(size, rectype)}]]></c>. - </p> - <p><em>'not': </em>Negates its single argument (anything other - than <c><![CDATA[false]]></c> gives <c><![CDATA[false]]></c>). - </p> - <p><em>'and': </em>Returns <c><![CDATA[true]]></c> if all its arguments - (variable length argument list) evaluate to <c><![CDATA[true]]></c>, else - <c><![CDATA[false]]></c>. Evaluation order is undefined. - </p> - <p><em>'or': </em>Returns <c><![CDATA[true]]></c> if any of its arguments - evaluates to <c><![CDATA[true]]></c>. Variable length argument - list. Evaluation order is undefined. - </p> - <p><em>andalso: </em>Like <c><![CDATA['and']]></c>, but quits evaluating its - arguments as soon as one argument evaluates to something else - than true. Arguments are evaluated left to right. - </p> - <p><em>orelse: </em>Like <c><![CDATA['or']]></c>, but quits evaluating as soon - as one of its arguments evaluates to <c><![CDATA[true]]></c>. Arguments are - evaluated left to right. - </p> - <p><em>'xor': </em>Only two arguments, of which one has to be true - and the other false to return <c><![CDATA[true]]></c>; otherwise - <c><![CDATA['xor']]></c> returns false. - </p> - <p><em>abs, element, hd, length, node, round, size, tl, trunc, '+', '-', '*', 'div', 'rem', 'band', 'bor', 'bxor', 'bnot', 'bsl', 'bsr', '>', '>=', '<', '=<', '=:=', '==', '=/=', '/=', self: </em>Work as the corresponding Erlang bif's (or - operators). In case of bad arguments, the result depends on - the context. In the <c><![CDATA[MatchConditions]]></c> part of the - expression, the test fails immediately (like in an Erlang - guard), but in the <c><![CDATA[MatchBody]]></c>, exceptions are implicitly - caught and the call results in the atom <c><![CDATA['EXIT']]></c>.</p> + <title>Functions Allowed in All Types of Match Specifications</title> + <p>The functions allowed in <c><![CDATA[match_spec]]></c> work as + follows:</p> + + <taglist> + <tag><c>is_atom</c>, <c>is_float</c>, <c>is_integer</c>, <c>is_list</c>, + <c>is_number</c>, <c>is_pid</c>, <c>is_port</c>, <c>is_reference</c>, + <c>is_tuple</c>, <c>is_map</c>, <c>is_binary</c>, <c>is_function</c> + </tag> + <item> + <p>Same as the corresponding guard tests in Erlang, return + <c><![CDATA[true]]></c> or <c><![CDATA[false]]></c>.</p> + </item> + <tag><c>is_record</c></tag> + <item> + <p>Takes an additional parameter, which <em>must</em> be the result + of <c><![CDATA[record_info(size, <record_type>)]]></c>, like in + <c><![CDATA[{is_record, '$1', rectype, record_info(size, + rectype)}]]></c>.</p> + </item> + <tag><c>'not'</c></tag> + <item> + <p>Negates its single argument (anything other + than <c><![CDATA[false]]></c> gives <c><![CDATA[false]]></c>).</p> + </item> + <tag><c>'and'</c></tag> + <item> + <p>Returns <c><![CDATA[true]]></c> if all its arguments (variable + length argument list) evaluate to <c><![CDATA[true]]></c>, otherwise + <c><![CDATA[false]]></c>. Evaluation order is undefined.</p> + </item> + <tag><c>'or'</c></tag> + <item> + <p>Returns <c><![CDATA[true]]></c> if any of its arguments + evaluates to <c><![CDATA[true]]></c>. Variable length argument + list. Evaluation order is undefined.</p> + </item> + <tag><c>'andalso'</c></tag> + <item> + <p>Works as <c><![CDATA['and']]></c>, but quits evaluating its + arguments when one argument evaluates to something else + than <c>true</c>. Arguments are evaluated left to right.</p> + </item> + <tag><c>'orelse'</c></tag> + <item> + <p>Works as <c><![CDATA['or']]></c>, but quits evaluating as soon + as one of its arguments evaluates to <c><![CDATA[true]]></c>. + Arguments are evaluated left to right.</p> + </item> + <tag><c>'xor'</c></tag> + <item> + <p>Only two arguments, of which one must be <c>true</c> and the + other <c>false</c> to return <c><![CDATA[true]]></c>; otherwise + <c><![CDATA['xor']]></c> returns false.</p> + </item> + <tag><c>abs</c>, <c>element</c>, <c>hd</c>, <c>length</c>, <c>node</c>, + <c>round</c>, <c>size</c>, <c>tl</c>, <c>trunc</c>, <c>'+'</c>, + <c>'-'</c>, <c>'*'</c>, <c>'div'</c>, <c>'rem'</c>, <c>'band'</c>, + <c>'bor'</c>, <c>'bxor'</c>, <c>'bnot'</c>, <c>'bsl'</c>, + <c>'bsr'</c>, <c>'>'</c>, <c>'>='</c>, <c>'<'</c>, <c>'=<'</c>, + <c>'=:='</c>, <c>'=='</c>, <c>'=/='</c>, <c>'/='</c>, + <c>self</c></tag> + <item> + <p>Same as the corresponding Erlang BIFs (or operators). In case of + bad arguments, the result depends on the context. In the + <c><![CDATA[MatchConditions]]></c> part of the expression, the test + fails immediately (like in an Erlang guard). In the + <c><![CDATA[MatchBody]]></c> part, exceptions are implicitly caught + and the call results in the atom <c><![CDATA['EXIT']]></c>.</p> + </item> + </taglist> </section> <section> - <title>Functions allowed only for tracing</title> - <p><em>is_seq_trace: </em>Returns <c><![CDATA[true]]></c> if a sequential - trace token is set for the current process, otherwise <c><![CDATA[false]]></c>. - </p> - <p><em>set_seq_token:</em> Works like - <c><![CDATA[seq_trace:set_token/2]]></c>, but returns <c><![CDATA[true]]></c> on success - and <c><![CDATA['EXIT']]></c> on error or bad argument. Only allowed in the - <c><![CDATA[MatchBody]]></c> part and only allowed when tracing. - </p> - <p><em>get_seq_token:</em> Works just like - <c><![CDATA[seq_trace:get_token/0]]></c>, and is only allowed in the - <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p><em>message:</em> Sets an additional message appended to the - trace message sent. One can only set one additional message in - the body; subsequent calls will replace the appended message. As - a special case, <c><![CDATA[{message, false}]]></c> disables sending of - trace messages ('call' and 'return_to') - for this function call, just like if the match_spec had not matched, - which can be useful if only the side effects of - the <c><![CDATA[MatchBody]]></c> are desired. - Another special case is <c><![CDATA[{message, true}]]></c> which - sets the default behavior, as if the function had no match_spec, - trace message is sent with no extra - information (if no other calls to <c><![CDATA[message]]></c> are placed - before <c><![CDATA[{message, true}]]></c>, it is in fact a "noop"). - </p> - <p>Takes one argument, the message. Returns <c><![CDATA[true]]></c> and can - only be used in the <c><![CDATA[MatchBody]]></c> part and when tracing. - </p> - <p><em>return_trace:</em> Causes a <c><![CDATA[return_from]]></c> trace - message to be sent upon return from the current function. - Takes no arguments, returns <c><![CDATA[true]]></c> and can only be used - in the <c><![CDATA[MatchBody]]></c> part when tracing. - If the process trace flag <c><![CDATA[silent]]></c> - is active the <c><![CDATA[return_from]]></c> trace message is inhibited. - </p> - <p>NOTE! If the traced function is tail recursive, this match - spec function destroys that property. - Hence, if a match spec executing this function is used on a - perpetual server process, it may only be active for a limited - time, or the emulator will eventually use all memory in the host - machine and crash. If this match_spec function is inhibited - using the <c><![CDATA[silent]]></c> process trace flag - tail recursiveness still remains. - </p> - <p><em>exception_trace:</em> Same as <em>return_trace</em>, - plus; if the traced function exits due to an exception, - an <c><![CDATA[exception_from]]></c> trace message is generated, - whether the exception is caught or not. - </p> - <p><em>process_dump:</em> Returns some textual information about - the current process as a binary. Takes no arguments and is only - allowed in the <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p><em>enable_trace:</em> With one parameter this function turns - on tracing like the Erlang call <c><![CDATA[erlang:trace(self(), true, [P2])]]></c>, where <c><![CDATA[P2]]></c> is the parameter to - <c><![CDATA[enable_trace]]></c>. With two parameters, the first parameter - should be either a process identifier or the registered name of - a process. In this case tracing is turned on for the designated - process in the same way as in the Erlang call <c><![CDATA[erlang:trace(P1, true, [P2])]]></c>, where P1 is the first and P2 is the second - argument. The process <c><![CDATA[P1]]></c> gets its trace messages sent to the same - tracer as the process executing the statement uses. <c><![CDATA[P1]]></c> - can <em>not</em> be one of the atoms <c><![CDATA[all]]></c>, <c><![CDATA[new]]></c> or - <c><![CDATA[existing]]></c> (unless, of course, they are registered names). - <c><![CDATA[P2]]></c> can <em>not</em> be <c><![CDATA[cpu_timestamp]]></c> nor - <c><![CDATA[tracer]]></c>. - Returns <c><![CDATA[true]]></c> and may only be used in - the <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p><em>disable_trace:</em> With one parameter this function - disables tracing like the Erlang call <c><![CDATA[erlang:trace(self(), false, [P2])]]></c>, where <c><![CDATA[P2]]></c> is the parameter to - <c><![CDATA[disable_trace]]></c>. With two parameters it works like the - Erlang call <c><![CDATA[erlang:trace(P1, false, [P2])]]></c>, where P1 can - be either a process identifier or a registered name and is given - as the first argument to the match_spec function. - <c><![CDATA[P2]]></c> can <em>not</em> be <c><![CDATA[cpu_timestamp]]></c> nor - <c><![CDATA[tracer]]></c>. Returns - <c><![CDATA[true]]></c> and may only be used in the <c><![CDATA[MatchBody]]></c> part - when tracing. - </p> - <p><em>trace:</em> With two parameters this function takes a list - of trace flags to disable as first parameter and a list - of trace flags to enable as second parameter. Logically, the - disable list is applied first, but effectively all changes - are applied atomically. The trace flags - are the same as for <c><![CDATA[erlang:trace/3]]></c> not including - <c><![CDATA[cpu_timestamp]]></c> but including <c><![CDATA[tracer]]></c>. If a - tracer is specified in both lists, the tracer in the - enable list takes precedence. If no tracer is specified the - same tracer as the process executing the match spec is - used. When using a <seealso marker="erl_tracer">tracer module</seealso> - the module has to be loaded before the match specification is executed. - If it is not loaded the match will fail. - With three parameters to this function the first is - either a process identifier or the registered name of a - process to set trace flags on, the second is the disable - list, and the third is the enable list. Returns - <c><![CDATA[true]]></c> if any trace property was changed for the - trace target process or <c><![CDATA[false]]></c> if not. It may only - be used in the <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p><em>caller:</em> - Returns the calling function as a tuple {Module, - Function, Arity} or the atom <c><![CDATA[undefined]]></c> if the calling - function cannot be determined. May only be used in the - <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p>Note that if a "technically built in function" (i.e. a - function not written in Erlang) is traced, the <c><![CDATA[caller]]></c> - function will sometimes return the atom <c><![CDATA[undefined]]></c>. The calling - Erlang function is not available during such calls. - </p> - <p><em>display:</em> For debugging purposes only; displays the - single argument as an Erlang term on stdout, which is seldom - what is wanted. Returns <c><![CDATA[true]]></c> and may only be used in the - <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p> <marker id="get_tcw"></marker> -<em>get_tcw:</em> - Takes no argument and returns the value of the node's trace - control word. The same is done by - <c><![CDATA[erlang:system_info(trace_control_word)]]></c>. - </p> - <p>The trace control word is a 32-bit unsigned integer intended for - generic trace control. The trace control word can be tested and - set both from within trace match specifications and with BIFs. - This call is only allowed when tracing. - </p> - <p> <marker id="set_tcw"></marker> -<em>set_tcw:</em> - Takes one unsigned integer argument, sets the value of - the node's trace control word to the value of the argument - and returns the previous value. The same is done by - <c><![CDATA[erlang:system_flag(trace_control_word, Value)]]></c>. It is only - allowed to use <c><![CDATA[set_tcw]]></c> in the <c><![CDATA[MatchBody]]></c> part - when tracing. - </p> - <p><em>silent:</em> - Takes one argument. If the argument is <c><![CDATA[true]]></c>, the call - trace message mode for the current process is set to silent - for this call and all subsequent, i.e call trace messages - are inhibited even if <c><![CDATA[{message, true}]]></c> is called in the - <c><![CDATA[MatchBody]]></c> part for a traced function. - </p> - <p>This mode can also be activated with the <c><![CDATA[silent]]></c> flag - to <c><![CDATA[erlang:trace/3]]></c>. - </p> - <p>If the argument is <c><![CDATA[false]]></c>, the call trace message mode - for the current process is set to normal (non-silent) for - this call and all subsequent. - </p> - <p>If the argument is neither <c><![CDATA[true]]></c> nor <c><![CDATA[false]]></c>, - the call trace message mode is unaffected.</p> + <title>Functions Allowed Only for Tracing</title> + <p>The functions allowed only for tracing work as follows:</p> + + <taglist> + <tag><c>is_seq_trace</c></tag> + <item> + <p>Returns <c><![CDATA[true]]></c> if a sequential trace token is set + for the current process, otherwise <c><![CDATA[false]]></c>.</p> + </item> + <tag><c>set_seq_token</c></tag> + <item> + <p>Works as <c><![CDATA[seq_trace:set_token/2]]></c>, but returns + <c><![CDATA[true]]></c> on success, and <c><![CDATA['EXIT']]></c> + on error or bad argument. Only allowed in the + <c><![CDATA[MatchBody]]></c> part and only allowed when tracing.</p> + </item> + <tag><c>get_seq_token</c></tag> + <item> + <p>Same as <c><![CDATA[seq_trace:get_token/0]]></c> and only + allowed in the <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>message</c></tag> + <item> + <p>Sets an additional message appended to the + trace message sent. One can only set one additional message in + the body. Later calls replace the appended message.</p> + <p>As a special case, <c><![CDATA[{message, false}]]></c> disables + sending of trace messages ('call' and 'return_to') for this function + call, just like if the match specification had not matched. + This can be useful if only the side effects of + the <c><![CDATA[MatchBody]]></c> part are desired.</p> + <p>Another special case is <c><![CDATA[{message, true}]]></c>, which + sets the default behavior, as if the function had no match + specification; trace message is sent with no extra information + (if no other calls to <c><![CDATA[message]]></c> are placed before + <c><![CDATA[{message, true}]]></c>, it is in fact a "noop").</p> + <p>Takes one argument: the message. Returns <c><![CDATA[true]]></c> + and can only be used in the <c><![CDATA[MatchBody]]></c> part and + when tracing.</p> + </item> + <tag><c>return_trace</c></tag> + <item> + <p>Causes a <c><![CDATA[return_from]]></c> trace message to be sent + upon return from the current function. Takes no arguments, returns + <c><![CDATA[true]]></c> and can only be used in the + <c><![CDATA[MatchBody]]></c> part when tracing. + If the process trace flag <c><![CDATA[silent]]></c> is active, the + <c><![CDATA[return_from]]></c> trace message is inhibited.</p> + <p><em>Warning:</em> If the traced function is tail-recursive, this + match specification function destroys that property. Hence, if a + match specification executing this function is used on a + perpetual server process, it can only be active for a limited + period of time, or the emulator will eventually use all memory in + the host machine and crash. If this match specification function is + inhibited using process trace flag <c><![CDATA[silent]]></c>, + tail-recursiveness still remains.</p> + </item> + <tag><c>exception_trace</c></tag> + <item> + <p>Works as <c>return_trace</c> plus; if the traced function exits + because of an exception, + an <c><![CDATA[exception_from]]></c> trace message is generated, + regardless of the exception is caught or not.</p> + </item> + <tag><c>process_dump</c></tag> + <item> + <p>Returns some textual information about + the current process as a binary. Takes no arguments and is only + allowed in the <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>enable_trace</c></tag> + <item> + <p>With one parameter this function turns on tracing like the Erlang + call <c><![CDATA[erlang:trace(self(), true, [P2])]]></c>, where + <c><![CDATA[P2]]></c> is the parameter to + <c><![CDATA[enable_trace]]></c>.</p> + <p>With two parameters, the first parameter is to be either a process + identifier or the registered name of a process. In this case tracing + is turned on for the designated process in the same way as in the + Erlang call <c><![CDATA[erlang:trace(P1, true, [P2])]]></c>, where + <c>P1</c> is the first and <c>P2</c> is the second argument. The + process <c><![CDATA[P1]]></c> gets its trace messages sent to the + same tracer as the process executing the statement uses. + <c><![CDATA[P1]]></c> <em>cannot</em> be one of the atoms + <c><![CDATA[all]]></c>, <c><![CDATA[new]]></c> or + <c><![CDATA[existing]]></c> (unless they are registered names). + <c><![CDATA[P2]]></c> <em>cannot</em> be + <c><![CDATA[cpu_timestamp]]></c> or <c><![CDATA[tracer]]></c>.</p> + <p>Returns <c><![CDATA[true]]></c> and can only be used in + the <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>disable_trace</c></tag> + <item> + <p>With one parameter this function disables tracing like the Erlang + call <c><![CDATA[erlang:trace(self(), false, [P2])]]></c>, where + <c><![CDATA[P2]]></c> is the parameter to + <c><![CDATA[disable_trace]]></c>.</p> + <p>With two parameters this function works as the Erlang call + <c><![CDATA[erlang:trace(P1, false, [P2])]]></c>, where <c>P1</c> + can be either a process identifier or a registered name and is + specified as the first argument to the match specification function. + <c><![CDATA[P2]]></c> <em>cannot</em> be + <c><![CDATA[cpu_timestamp]]></c> or <c><![CDATA[tracer]]></c>.</p> + <p>Returns <c><![CDATA[true]]></c> and can only be used in the + <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>trace</c></tag> + <item> + <p>With two parameters this function takes a list + of trace flags to disable as first parameter and a list + of trace flags to enable as second parameter. Logically, the + disable list is applied first, but effectively all changes + are applied atomically. The trace flags + are the same as for <c><![CDATA[erlang:trace/3]]></c>, + not including <c><![CDATA[cpu_timestamp]]></c>, but including + <c><![CDATA[tracer]]></c>.</p> + <p>If a tracer is specified in both lists, the tracer in the + enable list takes precedence. If no tracer is specified, the same + tracer as the process executing the match specification is used.</p> + <p>When using a <seealso marker="erl_tracer">tracer module</seealso>, + the module must be loaded before the match specification is + executed. If it is not loaded, the match fails.</p> + <p>With three parameters to this function, the first is + either a process identifier or the registered name of a + process to set trace flags on, the second is the disable + list, and the third is the enable list.</p> + <p>Returns <c><![CDATA[true]]></c> if any trace property was changed + for the trace target process, otherwise <c><![CDATA[false]]></c>. + Can only be used in the <c><![CDATA[MatchBody]]></c> part when + tracing.</p> + </item> + <tag><c>caller</c></tag> + <item> + <p>Returns the calling function as a tuple <c>{Module, Function, + Arity}</c> or the atom <c><![CDATA[undefined]]></c> if the calling + function cannot be determined. Can only be used in the + <c><![CDATA[MatchBody]]></c> part when tracing.</p> + <p>Notice that if a "technically built in function" (that is, a + function not written in Erlang) is traced, the + <c><![CDATA[caller]]></c> function sometimes returns the atom + <c><![CDATA[undefined]]></c>. The calling + Erlang function is not available during such calls.</p> + </item> + <tag><c>display</c></tag> + <item> + <p>For debugging purposes only. Displays the single argument as an + Erlang term on <c>stdout</c>, which is seldom what is wanted. + Returns <c><![CDATA[true]]></c> and can only be used in the + <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><marker id="get_tcw"/><c>get_tcw</c></tag> + <item> + <p>Takes no argument and returns the value of the node's trace + control word. The same is done by + <c><![CDATA[erlang:system_info(trace_control_word)]]></c>.</p> + <p>The trace control word is a 32-bit unsigned integer intended for + generic trace control. The trace control word can be tested and + set both from within trace match specifications and with BIFs. + This call is only allowed when tracing.</p> + </item> + <tag><marker id="set_tcw"/><c>set_tcw</c></tag> + <item> + <p>Takes one unsigned integer argument, sets the value of + the node's trace control word to the value of the argument, + and returns the previous value. The same is done by + <c><![CDATA[erlang:system_flag(trace_control_word, Value)]]></c>. + It is only allowed to use <c><![CDATA[set_tcw]]></c> in the + <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>silent</c></tag> + <item> + <p>Takes one argument. If the argument is <c><![CDATA[true]]></c>, + the call trace message mode for the current process is set to + silent for this call and all later calls, that is, call trace + messages are inhibited even if + <c><![CDATA[{message, true}]]></c> is called in the + <c><![CDATA[MatchBody]]></c> part for a traced function.</p> + <p>This mode can also be activated with flag + <c><![CDATA[silent]]></c> to + <c><![CDATA[erlang:trace/3]]></c>.</p> + <p>If the argument is <c><![CDATA[false]]></c>, the call trace + message mode for the current process is set to normal + (non-silent) for this call and all later calls.</p> + <p>If the argument is not <c><![CDATA[true]]></c> or + <c><![CDATA[false]]></c>, the call trace message mode is + unaffected.</p> + </item> + </taglist> </section> - <p><em>Note</em> that all "function calls" have to be tuples, - even if they take no arguments. The value of <c><![CDATA[self]]></c> is - the atom() <c><![CDATA[self]]></c>, but the value of <c><![CDATA[{self}]]></c> is - the pid() of the current process.</p> + + <note> + <p>All "function calls" must be tuples, even if they take no arguments. + The value of <c><![CDATA[self]]></c> is the atom() + <c><![CDATA[self]]></c>, but the value of <c><![CDATA[{self}]]></c> is + the pid() of the current process.</p> + </note> </section> - <marker id="match_target"></marker> <section> + <marker id="match_target"/> <title>Match target</title> <p>Each execution of a match specification is done against a match target term. The format and content of the target term @@ -422,217 +531,268 @@ </section> <section> - <title>Variables and literals</title> - <p>Variables take the form <c><![CDATA['$<number>']]></c> where - <c><![CDATA[<number>]]></c> is an integer between 0 (zero) and - 100000000 (1e+8), the behavior if the number is outside these - limits is <em>undefined</em>. In the <c><![CDATA[MatchHead]]></c> part, the special - variable <c><![CDATA['_']]></c> matches anything, and never gets bound (like - <c><![CDATA[_]]></c> in Erlang). In the <c><![CDATA[MatchCondition/MatchBody]]></c> - parts, no unbound variables are allowed, why <c><![CDATA['_']]></c> is - interpreted as itself (an atom). Variables can only be bound in - the <c><![CDATA[MatchHead]]></c> part. In the <c><![CDATA[MatchBody]]></c> and - <c><![CDATA[MatchCondition]]></c> parts, only variables bound previously may - be used. As a special case, in the - <c><![CDATA[MatchCondition/MatchBody]]></c> parts, the variable <c><![CDATA['$_']]></c> - expands to the whole <seealso marker="#match_target">match target</seealso> - term and the variable <c><![CDATA['$$']]></c> expands to a list - of the values of all bound variables in order - (i.e. <c><![CDATA[['$1','$2', ...]]]></c>). - </p> - <p>In the <c><![CDATA[MatchHead]]></c> part, all literals (except the variables - noted above) are interpreted as is. In the - <c><![CDATA[MatchCondition/MatchBody]]></c> parts, however, the - interpretation is in some ways different. Literals in the - <c><![CDATA[MatchCondition/MatchBody]]></c> can either be written as is, - which works for all literals except tuples, or by using the - special form <c><![CDATA[{const, T}]]></c>, where <c><![CDATA[T]]></c> is any Erlang - term. For tuple literals in the match_spec, one can also use - double tuple parentheses, i.e., construct them as a tuple of + <title>Variables and Literals</title> + <p>Variables take the form <c><![CDATA['$<number>']]></c>, where + <c><![CDATA[<number>]]></c> is an integer between 0 and + 100,000,000 (1e+8). The behavior if the number is outside these limits + is <em>undefined</em>. In the <c><![CDATA[MatchHead]]></c> part, the + special variable <c><![CDATA['_']]></c> matches anything, and never gets + bound (like <c><![CDATA[_]]></c> in Erlang).</p> + + <list type="bulleted"> + <item> + <p>In the <c><![CDATA[MatchCondition/MatchBody]]></c> parts, + no unbound variables are allowed, so <c><![CDATA['_']]></c> is + interpreted as itself (an atom). Variables can only be bound in the + <c><![CDATA[MatchHead]]></c> part.</p> + </item> + <item> + <p>In the <c><![CDATA[MatchBody]]></c> and + <c><![CDATA[MatchCondition]]></c> parts, only variables bound + previously can be used.</p> + </item> + <item> + <p>As a special case, the following apply in the + <c><![CDATA[MatchCondition/MatchBody]]></c> parts:</p> + <list type="bulleted"> + <item> + <p>The variable <c><![CDATA['$_']]></c> expands to the whole + <seealso marker="#match_target">match target</seealso> term. + </p> + </item> + <item> + <p>The variable <c><![CDATA['$$']]></c> expands to a list of the + values of all bound variables in order (that is, + <c><![CDATA[['$1','$2', ...]]]></c>).</p> + </item> + </list> + </item> + </list> + + <p>In the <c><![CDATA[MatchHead]]></c> part, all literals (except the + variables above) are interpreted "as is".</p> + + <p>In the <c><![CDATA[MatchCondition/MatchBody]]></c> parts, the + interpretation is in some ways different. Literals in these parts + can either be written "as is", which works for all literals except + tuples, or by using the special form <c><![CDATA[{const, T}]]></c>, + where <c><![CDATA[T]]></c> is any Erlang term.</p> + + <p>For tuple literals in the match specification, double tuple parentheses + can also be used, that is, construct them as a tuple of arity one containing a single tuple, which is the one to be constructed. The "double tuple parenthesis" syntax is useful to construct tuples from already bound variables, like in - <c><![CDATA[{{'$1', [a,b,'$2']}}]]></c>. Some examples may be needed: - </p> + <c><![CDATA[{{'$1', [a,b,'$2']}}]]></c>. Examples:</p> + <table> <row> - <cell align="left" valign="middle">Expression </cell> - <cell align="left" valign="middle">Variable bindings </cell> - <cell align="left" valign="middle">Result </cell> + <cell align="left" valign="middle"><em>Expression</em></cell> + <cell align="left" valign="middle"><em>Variable Bindings</em></cell> + <cell align="left" valign="middle"><em>Result</em></cell> </row> <row> - <cell align="left" valign="middle">{{'$1','$2'}} </cell> + <cell align="left" valign="middle">{{'$1','$2'}}</cell> <cell align="left" valign="middle">'$1' = a, '$2' = b</cell> <cell align="left" valign="middle">{a,b}</cell> </row> <row> - <cell align="left" valign="middle">{const, {'$1', '$2'}} </cell> - <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">{const, {'$1', '$2'}}</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">{'$1', '$2'}</cell> </row> <row> - <cell align="left" valign="middle">a </cell> - <cell align="left" valign="middle">doesn't matter </cell> + <cell align="left" valign="middle">a</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">a</cell> </row> <row> - <cell align="left" valign="middle">'$1' </cell> - <cell align="left" valign="middle">'$1' = [] </cell> + <cell align="left" valign="middle">'$1'</cell> + <cell align="left" valign="middle">'$1' = []</cell> <cell align="left" valign="middle">[]</cell> </row> <row> - <cell align="left" valign="middle">['$1'] </cell> - <cell align="left" valign="middle">'$1' = [] </cell> + <cell align="left" valign="middle">['$1']</cell> + <cell align="left" valign="middle">'$1' = []</cell> <cell align="left" valign="middle">[[]]</cell> </row> <row> - <cell align="left" valign="middle">[{{a}}] </cell> - <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">[{{a}}]</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">[{a}]</cell> </row> <row> - <cell align="left" valign="middle">42 </cell> - <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">42</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">42</cell> </row> <row> - <cell align="left" valign="middle">"hello" </cell> - <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">"hello"</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">"hello"</cell> </row> <row> - <cell align="left" valign="middle">$1 </cell> - <cell align="left" valign="middle">doesn't matter</cell> - <cell align="left" valign="middle">49 (the ASCII value for the character '1')</cell> + <cell align="left" valign="middle">$1</cell> + <cell align="left" valign="middle">Irrelevant</cell> + <cell align="left" valign="middle">49 (the ASCII value for + character '1')</cell> </row> - <tcaption>Literals in the MatchCondition/MatchBody parts of a match_spec</tcaption> + <tcaption>Literals in MatchCondition/MatchBody Parts of a Match + Specification</tcaption> </table> </section> <section> - <title>Execution of the match</title> + <title>Execution of the Match</title> <p>The execution of the match expression, when the runtime system - decides whether a trace message should be sent, goes as follows: - </p> - <p>For each tuple in the <c><![CDATA[MatchExpression]]></c> list and while no - match has succeeded:</p> - <list type="bulleted"> - <item>Match the <c><![CDATA[MatchHead]]></c> part against the - match target term, - binding the <c><![CDATA['$<number>']]></c> variables (much like in - <c><![CDATA[ets:match/2]]></c>). - If the <c><![CDATA[MatchHead]]></c> cannot match the arguments, the match fails. - </item> - <item>Evaluate each <c><![CDATA[MatchCondition]]></c> (where only - <c><![CDATA['$<number>']]></c> variables previously bound in the - <c><![CDATA[MatchHead]]></c> can occur) and expect it to return the atom - <c><![CDATA[true]]></c>. As soon as a condition does not evaluate to - <c><![CDATA[true]]></c>, the match fails. If any BIF call generates an - exception, also fail. + decides whether a trace message is to be sent, is as follows:</p> + + <p>For each tuple in the <c><![CDATA[MatchExpression]]></c> list and while + no match has succeeded:</p> + + <list type="ordered"> + <item> + <p>Match the <c><![CDATA[MatchHead]]></c> part against the match target + term, binding the <c><![CDATA['$<number>']]></c> variables + (much like in <c><![CDATA[ets:match/2]]></c>). If the + <c><![CDATA[MatchHead]]></c> part cannot match the arguments, the + match fails.</p> </item> <item> + <p>Evaluate each <c><![CDATA[MatchCondition]]></c> (where only + <c><![CDATA['$<number>']]></c> variables previously bound in the + <c><![CDATA[MatchHead]]></c> part can occur) and expect it to return + the atom <c><![CDATA[true]]></c>. When a condition does not evaluate + to <c><![CDATA[true]]></c>, the match fails. If any BIF call + generates an exception, the match also fails.</p> + </item> + <item> + <p>Two cases can occur:</p> <list type="bulleted"> - <item><em>If the match_spec is executing when tracing:</em><br></br> - Evaluate each <c><![CDATA[ActionTerm]]></c> in the same way as the - <c><![CDATA[MatchConditions]]></c>, but completely ignore the return - values. Regardless of what happens in this part, the match has - succeeded.</item> - <item><em>If the match_spec is executed when selecting objects from an ETS table:</em><br></br> - Evaluate the expressions in order and return the value of - the last expression (typically there is only one expression - in this context)</item> + <item> + <p>If the match specification is executing when tracing:</p> + <p>Evaluate each <c><![CDATA[ActionTerm]]></c> in the same way as + the <c><![CDATA[MatchConditions]]></c>, but ignore the return + values. Regardless of what happens in this part, the match has + succeeded.</p> + </item> + <item> + <p>If the match specification is executed when selecting objects + from an ETS table:</p> + <p>Evaluate the expressions in order and return the value of + the last expression (typically there is only one expression + in this context).</p> + </item> </list> </item> </list> </section> <section> - <title>Differences between match specifications in ETS and tracing</title> - <p>ETS match specifications are there to produce a return - value. Usually the <c><![CDATA[MatchBody]]></c> contains one single - <c><![CDATA[ConditionExpression]]></c> which defines the return value without having - any side effects. Calls with side effects are not allowed in the - ETS context.</p> + <marker id="differences_ets_tracing"/> + <title>Differences between Match Specifications in ETS and Tracing</title> + <p>ETS match specifications produce a return value. + Usually the <c><![CDATA[MatchBody]]></c> contains one single + <c><![CDATA[ConditionExpression]]></c> that defines the return value + without any side effects. Calls with side effects are not allowed in + the ETS context.</p> + <p>When tracing there is no return value to produce, the - match specification either matches or doesn't. The effect when the - expression matches is a trace message rather then a returned - term. The <c><![CDATA[ActionTerm]]></c>'s are executed as in an imperative - language, i.e. for their side effects. Functions with side effects + match specification either matches or does not. The effect when the + expression matches is a trace message rather than a returned + term. The <c><![CDATA[ActionTerm]]></c>s are executed as in an imperative + language, that is, for their side effects. Functions with side effects are also allowed when tracing.</p> </section> <section> <title>Tracing Examples</title> - <p>Match an argument list of three where the first and third arguments + <p>Match an argument list of three, where the first and third arguments are equal:</p> + <code type="none"><![CDATA[ [{['$1', '_', '$1'], [], []}] ]]></code> - <p>Match an argument list of three where the second argument is - a number greater than three:</p> + + <p>Match an argument list of three, where the second argument is + a number > 3:</p> + <code type="none"><![CDATA[ [{['_', '$1', '_'], [{ '>', '$1', 3}], []}] ]]></code> - <p>Match an argument list of three, where the third argument - is a tuple containing argument one and two <em>or</em> a list - beginning with argument one and two (i. e. <c><![CDATA[[a,b,[a,b,c]]]]></c> or - <c><![CDATA[[a,b,{a,b}]]]></c>): - </p> + + <p>Match an argument list of three, where the third argument is + either a tuple containing argument one and two, <em>or</em> a list + beginning with argument one and two (that is, + <c><![CDATA[[a,b,[a,b,c]]]]></c> or <c><![CDATA[[a,b,{a,b}]]]></c>):</p> + <code type="none"><![CDATA[ [{['$1', '$2', '$3'], - [{orelse, + [{'orelse', {'=:=', '$3', {{'$1','$2'}}}, {'and', {'=:=', '$1', {hd, '$3'}}, {'=:=', '$2', {hd, {tl, '$3'}}}}}], []}] ]]></code> - <p>The above problem may also be solved like this:</p> + + <p>The above problem can also be solved as follows:</p> + <code type="none"><![CDATA[ [{['$1', '$2', {'$1', '$2}], [], []}, {['$1', '$2', ['$1', '$2' | '_']], [], []}] ]]></code> - <p>Match two arguments where the first is a tuple beginning with - a list which in turn begins with the second argument times - two (i. e. [{[4,x],y},2] or [{[8], y, z},4])</p> + + <p>Match two arguments, where the first is a tuple beginning with + a list that in turn begins with the second argument times + two (that is, <c>[{[4,x],y},2]</c> or <c>[{[8], y, z},4])</c>:</p> + <code type="none"><![CDATA[ [{['$1', '$2'],[{'=:=', {'*', 2, '$2'}, {hd, {element, 1, '$1'}}}], []}] ]]></code> + <p>Match three arguments. When all three are equal and are - numbers, append the process dump to the trace message, else - let the trace message be as is, but set the sequential trace - token label to 4711.</p> + numbers, append the process dump to the trace message, otherwise + let the trace message be "as is", but set the sequential trace + token label to 4711:</p> + <code type="none"><![CDATA[ [{['$1', '$1', '$1'], [{is_number, '$1'}], [{message, {process_dump}}]}, {'_', [], [{set_seq_token, label, 4711}]}] ]]></code> - <p>As can be noted above, the parameter list can be matched - against a single <c><![CDATA[MatchVariable]]></c> or an <c><![CDATA['_']]></c>. To replace the - whole - parameter list with a single variable is a special case. In all - other cases the <c><![CDATA[MatchHead]]></c> has to be a <em>proper</em> list. - </p> - <p>Only generate trace message if trace control word is set to 1:</p> + + <p>As can be noted above, the parameter list can be matched against a + single <c><![CDATA[MatchVariable]]></c> or an <c><![CDATA['_']]></c>. + To replace the whole parameter list with a single variable is a special + case. In all other cases the <c><![CDATA[MatchHead]]></c> must be a + <em>proper</em> list.</p> + + <p>Generate a trace message only if the trace control word is set to 1:</p> + <code type="none"><![CDATA[ [{'_', [{'==',{get_tcw},{const, 1}}], []}] ]]></code> - <p>Only generate trace message if there is a seq trace token:</p> + + <p>Generate a trace message only if there is a <c>seq_trace</c> token:</p> + <code type="none"><![CDATA[ [{'_', [{'==',{is_seq_trace},{const, 1}}], []}] ]]></code> - <p>Remove 'silent' trace flag when first argument is 'verbose' - and add it when it is 'silent':</p> + + <p>Remove the <c>'silent'</c> trace flag when the first argument is + <c>'verbose'</c>, and add it when it is <c>'silent':</c></p> + <code type="none"><![CDATA[ [{'$1', [{'==',{hd, '$1'},verbose}], @@ -641,14 +801,19 @@ [{'==',{hd, '$1'},silent}], [{trace, [],[silent]}]}] ]]></code> - <p>Add return_trace message if function is of arity 3:</p> + + <p>Add a <c>return_trace</c> message if the function is of arity 3:</p> + <code type="none"><![CDATA[ [{'$1', [{'==',{length, '$1'},3}], [{return_trace}]}, {'_',[],[]}] ]]></code> - <p>Only generate trace message if function is of arity 3 and first argument is 'trace':</p> + + <p>Generate a trace message only if the function is of arity 3 and the + first argument is <c>'trace'</c>:</p> + <code type="none"><![CDATA[ [{['trace','$2','$3'], [], @@ -659,29 +824,35 @@ <section> <title>ETS Examples</title> - <p>Match all objects in an ets table where the first element is - the atom 'strider' and the tuple arity is 3 and return the whole - object.</p> + <p>Match all objects in an ETS table, where the first element is + the atom <c>'strider'</c> and the tuple arity is 3, and return the whole + object:</p> + <code type="none"><![CDATA[ [{{strider,'_','_'}, [], ['$_']}] ]]></code> - <p>Match all objects in an ets table with arity > 1 and the first - element is 'gandalf', return element 2.</p> + + <p>Match all objects in an ETS table with arity > 1 and the first + element is 'gandalf', and return element 2:</p> + <code type="none"><![CDATA[ [{'$1', [{'==', gandalf, {element, 1, '$1'}},{'>=',{size, '$1'},2}], [{element,2,'$1'}]}] ]]></code> - <p>In the above example, if the first element had been the key, - it's much more efficient to match that key in the <c><![CDATA[MatchHead]]></c> - part than in the <c><![CDATA[MatchConditions]]></c> part. The search space of - the tables is restricted with regards to the <c><![CDATA[MatchHead]]></c> so - that only objects with the matching key are searched. - </p> - <p>Match tuples of 3 elements where the second element is either - 'merry' or 'pippin', return the whole objects.</p> + + <p>In this example, if the first element had been the key, it is + much more efficient to match that key in the <c><![CDATA[MatchHead]]></c> + part than in the <c><![CDATA[MatchConditions]]></c> part. + The search space of the tables is restricted with regards to the + <c><![CDATA[MatchHead]]></c> so + that only objects with the matching key are searched.</p> + + <p>Match tuples of three elements, where the second element is either + <c>'merry'</c> or <c>'pippin'</c>, and return the whole objects:</p> + <code type="none"><![CDATA[ [{{'_',merry,'_'}, [], @@ -690,8 +861,9 @@ [], ['$_']}] ]]></code> - <p>The function <c><![CDATA[ets:test_ms/2]]></c> can be useful for testing - complicated ets matches.</p> + + <p>Function <seealso marker="stdlib:ets#test_ms/2"><c>ets:test_ms/2></c></seealso> + can be useful for testing complicated ETS matches.</p> </section> </chapter> |