diff options
author | Sverker Eriksson <sverker@erlang.org> | 2017-08-30 20:55:08 +0200 |
---|---|---|
committer | Sverker Eriksson <sverker@erlang.org> | 2017-08-30 20:55:08 +0200 |
commit | 7c67bbddb53c364086f66260701bc54a61c9659c (patch) | |
tree | 92ab0d4b91d5e2f6e7a3f9d61ea25089e8a71fe0 /lib/stdlib/doc/src/ms_transform.xml | |
parent | 97dc5e7f396129222419811c173edc7fa767b0f8 (diff) | |
parent | 3b7a6ffddc819bf305353a593904cea9e932e7dc (diff) | |
download | erlang-7c67bbddb53c364086f66260701bc54a61c9659c.tar.gz |
Merge tag 'OTP-19.0' into sverker/19/binary_to_atom-utf8-crash/ERL-474/OTP-14590
Diffstat (limited to 'lib/stdlib/doc/src/ms_transform.xml')
-rw-r--r-- | lib/stdlib/doc/src/ms_transform.xml | 981 |
1 files changed, 561 insertions, 420 deletions
diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml index ad5f8bd5ac..0a05fa37c5 100644 --- a/lib/stdlib/doc/src/ms_transform.xml +++ b/lib/stdlib/doc/src/ms_transform.xml @@ -1,23 +1,24 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>2002</year><year>2011</year> + <year>2002</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -27,65 +28,81 @@ <docno>1</docno> <approved>Bjarne Däcker</approved> <checked></checked> - <date>99-02-09</date> + <date>1999-02-09</date> <rev>C</rev> - <file>ms_transform.sgml</file> + <file>ms_transform.xml</file> </header> <module>ms_transform</module> - <modulesummary>Parse_transform that translates fun syntax into match specifications. </modulesummary> + <modulesummary>A parse transformation that translates fun syntax into match + specifications.</modulesummary> <description> <marker id="top"></marker> - <p>This module implements the parse_transform that makes calls to - <c>ets</c> and <c>dbg</c>:<c>fun2ms/1</c> translate into literal - match specifications. It also implements the back end for the same - functions when called from the Erlang shell.</p> - <p>The translations from fun's to match_specs - is accessed through the two "pseudo - functions" <c>ets:fun2ms/1</c> and <c>dbg:fun2ms/1</c>.</p> - <p>Actually this introduction is more or less an introduction to the - whole concept of match specifications. Since everyone trying to use - <c>ets:select</c> or <c>dbg</c> seems to end up reading - this page, it seems in good place to explain a little more than - just what this module does.</p> - <p>There are some caveats one should be aware of, please read through - the whole manual page if it's the first time you're using the - transformations. </p> - <p>Match specifications are used more or less as filters. - They resemble usual Erlang matching in a list comprehension or in - a <c>fun</c> used in conjunction with <c>lists:foldl</c> etc. The - syntax of pure match specifications is somewhat awkward though, as - they are made up purely by Erlang terms and there is no syntax in the - language to make the match specifications more readable.</p> - <p>As the match specifications execution and structure is quite like - that of a fun, it would for most programmers be more straight forward - to simply write it using the familiar fun syntax and having that - translated into a match specification automatically. Of course a real - fun is more powerful than the match specifications allow, but bearing - the match specifications in mind, and what they can do, it's still + <p>This module provides the parse transformation that makes calls to + <seealso marker="ets"><c>ets</c></seealso> and + <seealso marker="runtime_tools:dbg#fun2ms/1"><c>dbg:fun2ms/1</c></seealso> + translate into literal match specifications. It also provides the back end + for the same functions when called from the Erlang shell.</p> + + <p>The translation from funs to match specifications + is accessed through the two "pseudo functions" + <seealso marker="ets#fun2ms/1"><c>ets:fun2ms/1</c></seealso> and + <seealso marker="runtime_tools:dbg#fun2ms/1"><c>dbg:fun2ms/1</c></seealso>.</p> + + <p>As everyone trying to use + <seealso marker="ets#select/1"><c>ets:select/2</c></seealso> or + <seealso marker="runtime_tools:dbg"><c>dbg</c></seealso> seems to end up + reading this manual page, this description is an introduction to the + concept of match specifications.</p> + + <p>Read the whole manual page if it is the first time you are using + the transformations.</p> + + <p>Match specifications are used more or less as filters. They resemble + usual Erlang matching in a list comprehension or in a fun used with + <seealso marker="lists#foldl/3"><c>lists:foldl/3</c></seealso>, and so on. + However, the syntax of pure match specifications is awkward, as + they are made up purely by Erlang terms, and the language has no + syntax to make the match specifications more readable.</p> + + <p>As the execution and structure of the match specifications are like + that of a fun, it is more straightforward + to write it using the familiar fun syntax and to have that + translated into a match specification automatically. A real fun is + clearly more powerful than the match specifications allow, but bearing + the match specifications in mind, and what they can do, it is still more convenient to write it all as a fun. This module contains the - code that simply translates the fun syntax into match_spec terms.</p> - <p>Let's start with an ets example. Using <c>ets:select</c> and - a match specification, one can filter out rows of a table and construct - a list of tuples containing relevant parts of the data in these - rows. Of course one could use <c>ets:foldl</c> instead, but the - select call is far more efficient. Without the translation, one has to - struggle with writing match specifications terms to accommodate this, - or one has to resort to the less powerful - <c>ets:match(_object)</c> calls, or simply give up and use - the more inefficient method of <c>ets:foldl</c>. Using the - <c>ets:fun2ms</c> transformation, a <c>ets:select</c> call - is at least as easy to write as any of the alternatives.</p> - <p>As an example, consider a simple table of employees:</p> + code that translates the fun syntax into match specification + terms.</p> + </description> + + <section> + <title>Example 1</title> + <p>Using <seealso marker="ets#select/2"><c>ets:select/2</c></seealso> + and a match specification, one can filter out rows of + a table and construct a list of tuples containing relevant parts + of the data in these rows. + One can use <seealso marker="ets#foldl/3"><c>ets:foldl/3</c></seealso> + instead, but the <c>ets:select/2</c> call is far more efficient. + Without the translation provided by <c>ms_transform</c>, + one must struggle with writing match specifications terms + to accommodate this.</p> + + <p>Consider a simple table of employees:</p> + <code type="none"> -record(emp, {empno, %Employee number as a string, the key surname, %Surname of the employee givenname, %Given name of employee - dept, %Department one of {dev,sales,prod,adm} - empyear}). %Year the employee was employed </code> + dept, %Department, one of {dev,sales,prod,adm} + empyear}). %Year the employee was employed</code> + <p>We create the table using:</p> + <code type="none"> -ets:new(emp_tab,[{keypos,#emp.empno},named_table,ordered_set]). </code> - <p>Let's also fill it with some randomly chosen data for the examples:</p> +ets:new(emp_tab, [{keypos,#emp.empno},named_table,ordered_set]).</code> + + <p>We fill the table with randomly chosen data:</p> + <code type="none"> [{emp,"011103","Black","Alfred",sales,2000}, {emp,"041231","Doe","John",prod,2001}, @@ -95,167 +112,204 @@ ets:new(emp_tab,[{keypos,#emp.empno},named_table,ordered_set]). </code> {emp,"535216","Chalker","Samuel",adm,1998}, {emp,"789789","Harrysson","Joe",adm,1996}, {emp,"963721","Scott","Juliana",dev,2003}, - {emp,"989891","Brown","Gabriel",prod,1999}] </code> - <p>Now, the amount of data in the table is of course to small to justify - complicated ets searches, but on real tables, using <c>select</c> to get - exactly the data you want will increase efficiency remarkably.</p> - <p>Lets say for example that we'd want the employee numbers of - everyone in the sales department. One might use <c>ets:match</c> - in such a situation:</p> + {emp,"989891","Brown","Gabriel",prod,1999}]</code> + + <p>Assuming that we want the employee numbers of everyone in the sales + department, there are several ways.</p> + + <p><c>ets:match/2</c> can be used:</p> + <pre> 1> <input>ets:match(emp_tab, {'_', '$1', '_', '_', sales, '_'}).</input> -[["011103"],["076324"]] </pre> - <p>Even though <c>ets:match</c> does not require a full match - specification, but a simpler type, it's still somewhat unreadable, and - one has little control over the returned result, it's always a list of - lists. OK, one might use <c>ets:foldl</c> or - <c>ets:foldr</c> instead:</p> +[["011103"],["076324"]]</pre> + + <p><c>ets:match/2</c> uses a simpler type of match specification, + but it is still unreadable, and one has little control over the + returned result. It is always a list of lists.</p> + + <p><seealso marker="ets#foldl/3"><c>ets:foldl/3</c></seealso> or + <seealso marker="ets#foldr/3"><c>ets:foldr/3</c></seealso> can be used to avoid the nested lists:</p> + <code type="none"> ets:foldr(fun(#emp{empno = E, dept = sales},Acc) -> [E | Acc]; (_,Acc) -> Acc end, [], - emp_tab). </code> - <p>Running that would result in <c>["011103","076324"]</c> - , which at least gets rid of the extra lists. The fun is also quite + emp_tab).</code> + + <p>The result is <c>["011103","076324"]</c>. The fun is straightforward, so the only problem is that all the data from the - table has to be transferred from the table to the calling process for - filtering. That's inefficient compared to the <c>ets:match</c> + table must be transferred from the table to the calling process for + filtering. That is inefficient compared to the <c>ets:match/2</c> call where the filtering can be done "inside" the emulator and only - the result is transferred to the process. Remember that ets tables are - all about efficiency, if it wasn't for efficiency all of ets could be - implemented in Erlang, as a process receiving requests and sending - answers back. One uses ets because one wants performance, and - therefore one wouldn't want all of the table transferred to the - process for filtering. OK, let's look at a pure - <c>ets:select</c> call that does what the <c>ets:foldr</c> - does:</p> + the result is transferred to the process.</p> + + <p>Consider a "pure" <c>ets:select/2</c> call that does what + <c>ets:foldr</c> does:</p> + <code type="none"> -ets:select(emp_tab,[{#emp{empno = '$1', dept = sales, _='_'},[],['$1']}]). </code> - <p>Even though the record syntax is used, it's still somewhat hard to +ets:select(emp_tab, [{#emp{empno = '$1', dept = sales, _='_'},[],['$1']}]).</code> + + <p>Although the record syntax is used, it is still hard to read and even harder to write. The first element of the tuple, - <c>#emp{empno = '$1', dept = sales, _='_'}</c> tells what to - match, elements not matching this will not be returned at all, as in - the <c>ets:match</c> example. The second element, the empty list - is a list of guard expressions, which we need none, and the third + <c>#emp{empno = '$1', dept = sales, _='_'}</c>, tells what to + match. Elements not matching this are not returned, as in + the <c>ets:match/2</c> example. The second element, the empty list, + is a list of guard expressions, which we do not need. The third element is the list of expressions constructing the return value (in - ets this almost always is a list containing one single term). In our - case <c>'$1'</c> is bound to the employee number in the head - (first element of tuple), and hence it is the employee number that is - returned. The result is <c>["011103","076324"]</c>, just as in - the <c>ets:foldr</c> example, but the result is retrieved much - more efficiently in terms of execution speed and memory consumption.</p> - <p>We have one efficient but hardly readable way of doing it and one - inefficient but fairly readable (at least to the skilled Erlang - programmer) way of doing it. With the use of <c>ets:fun2ms</c>, - one could have something that is as efficient as possible but still is - written as a filter using the fun syntax:</p> + ETS this is almost always a list containing one single term). + In our case <c>'$1'</c> is bound to the employee number in the head + (first element of the tuple), and hence the employee number is + returned. The result is <c>["011103","076324"]</c>, as in + the <c>ets:foldr/3</c> example, but the result is retrieved much + more efficiently in terms of execution speed and + memory consumption.</p> + + <p>Using <c>ets:fun2ms/1</c>, we can combine the ease of use of + the <c>ets:foldr/3</c> and the efficiency of the pure + <c>ets:select/2</c> example:</p> + <code type="none"> -include_lib("stdlib/include/ms_transform.hrl"). -% ... - ets:select(emp_tab, ets:fun2ms( fun(#emp{empno = E, dept = sales}) -> E - end)). </code> - <p>This may not be the shortest of the expressions, but it requires no - special knowledge of match specifications to read. The fun's head - should simply match what you want to filter out and the body returns - what you want returned. As long as the fun can be kept within the - limits of the match specifications, there is no need to transfer all - data of the table to the process for filtering as in the - <c>ets:foldr</c> example. In fact it's even easier to read then - the <c>ets:foldr</c> example, as the select call in itself - discards anything that doesn't match, while the fun of the - <c>foldr</c> call needs to handle both the elements matching and - the ones not matching.</p> - <p>It's worth noting in the above <c>ets:fun2ms</c> example that one - needs to include <c>ms_transform.hrl</c> in the source code, as this is - what triggers the parse transformation of the <c>ets:fun2ms</c> call - to a valid match specification. This also implies that the - transformation is done at compile time (except when called from the - shell of course) and therefore will take no resources at all in - runtime. So although you use the more intuitive fun syntax, it gets as - efficient in runtime as writing match specifications by hand.</p> - <p>Let's look at some more <c>ets</c> examples. Let's say one - wants to get all the employee numbers of any employee hired before the - year 2000. Using <c>ets:match</c> isn't an alternative here as - relational operators cannot be expressed there. Once again, an - <c>ets:foldr</c> could do it (slowly, but correct):</p> + end)).</code> + + <p>This example requires no special knowledge of match + specifications to understand. The head of the fun matches what + you want to filter out and the body returns what you want + returned. As long as the fun can be kept within the limits of the + match specifications, there is no need to transfer all table data + to the process for filtering as in the <c>ets:foldr/3</c> + example. It is easier to read than the <c>ets:foldr/3</c> example, + as the select call in itself discards anything that does not + match, while the fun of the <c>ets:foldr/3</c> call needs to + handle both the elements matching and the ones not matching.</p> + + <p>In the <c>ets:fun2ms/1</c> example above, it is needed to + include <c>ms_transform.hrl</c> in the source code, as this is + what triggers the parse transformation of the <c>ets:fun2ms/1</c> + call to a valid match specification. This also implies that the + transformation is done at compile time (except when called from + the shell) and therefore takes no resources in runtime. That is, + although you use the more intuitive fun syntax, it gets as + efficient in runtime as writing match specifications by hand.</p> + </section> + + <section> + <title>Example 2</title> + <p>Assume that we want to get all the employee numbers of employees + hired before year 2000. Using <c>ets:match/2</c> is not + an alternative here, as relational operators cannot be + expressed there. + Once again, <c>ets:foldr/3</c> can do it (slowly, but correct):</p> + <code type="none"><![CDATA[ ets:foldr(fun(#emp{empno = E, empyear = Y},Acc) when Y < 2000 -> [E | Acc]; (_,Acc) -> Acc end, [], emp_tab). ]]></code> - <p>The result will be - <c>["052341","076324","535216","789789","989891"]</c>, as - expected. Now the equivalent expression using a handwritten match - specification would look something like this:</p> + + <p>The result is <c>["052341","076324","535216","789789","989891"]</c>, + as expected. The equivalent expression using a handwritten match + specification would look like this:</p> + <code type="none"><![CDATA[ -ets:select(emp_tab,[{#emp{empno = '$1', empyear = '$2', _='_'}, +ets:select(emp_tab, [{#emp{empno = '$1', empyear = '$2', _='_'}, [{'<', '$2', 2000}], ['$1']}]). ]]></code> - <p>This gives the same result, the <c><![CDATA[[{'<', '$2', 2000}]]]></c> is in - the guard part and therefore discards anything that does not have a - empyear (bound to '$2' in the head) less than 2000, just as the guard - in the <c>foldl</c> example. Lets jump on to writing it using - <c>ets:fun2ms</c></p> + + <p>This gives the same result. <c><![CDATA[[{'<', '$2', 2000}]]]></c> is in + the guard part and therefore discards anything that does not have an + <c>empyear</c> (bound to <c>'$2'</c> in the head) less than 2000, as + the guard in the <c>foldr/3</c> example.</p> + + <p>We write it using <c>ets:fun2ms/1</c>:</p> + <code type="none"><![CDATA[ -include_lib("stdlib/include/ms_transform.hrl"). -% ... - ets:select(emp_tab, ets:fun2ms( fun(#emp{empno = E, empyear = Y}) when Y < 2000 -> - E + E end)). ]]></code> - <p>Obviously readability is gained by using the parse transformation.</p> - <p>I'll show some more examples without the tiresome - comparing-to-alternatives stuff. Let's say we'd want the whole object - matching instead of only one element. We could of course assign a - variable to every part of the record and build it up once again in the - body of the <c>fun</c>, but it's easier to do like this:</p> + </section> + + <section> + <title>Example 3</title> + <p>Assume that we want the whole object matching instead of only one + element. One alternative is to assign a variable to every part + of the record and build it up once again in the body of the fun, but + the following is easier:</p> + <code type="none"><![CDATA[ ets:select(emp_tab, ets:fun2ms( fun(Obj = #emp{empno = E, empyear = Y}) when Y < 2000 -> Obj - end)). ]]></code> - <p>Just as in ordinary Erlang matching, you can bind a variable to the - whole matched object using a "match in then match", i.e. a - <c>=</c>. Unfortunately this is not general in <c>fun's</c> translated - to match specifications, only on the "top level", i.e. matching the - <em>whole</em> object arriving to be matched into a separate variable, - is it allowed. For the one's used to writing match specifications by - hand, I'll have to mention that the variable A will simply be - translated into '$_'. It's not general, but it has very common usage, - why it is handled as a special, but useful, case. If this bothers you, - the pseudo function <c>object</c> also returns the whole matched - object, see the part about caveats and limitations below.</p> - <p>Let's do something in the <c>fun</c>'s body too: Let's say - that someone realizes that there are a few people having an employee - number beginning with a zero (<c>0</c>), which shouldn't be - allowed. All those should have their numbers changed to begin with a - one (<c>1</c>) instead and one wants the - list <c><![CDATA[[{<Old empno>,<New empno>}]]]></c> created:</p> + end)).]]></code> + + <p>As in ordinary Erlang matching, you can bind a variable to the + whole matched object using a "match inside the match", that is, a + <c>=</c>. Unfortunately in funs translated to match specifications, + it is allowed only at the "top-level", that is, + matching the <em>whole</em> object arriving to be matched + into a separate variable. + If you are used to writing match specifications by hand, we + mention that variable A is simply translated into '$_'. + Alternatively, pseudo function <c>object/0</c> + also returns the whole matched object, see section + <seealso marker="#warnings_and_restrictions"> + Warnings and Restrictions</seealso>.</p> + </section> + + <section> + <title>Example 4</title> + <p>This example concerns the body of the fun. Assume that all employee + numbers beginning with zero (<c>0</c>) must be changed to begin with + one (<c>1</c>) instead, and that we want to create the list + <c><![CDATA[[{<Old empno>,<New empno>}]]]></c>:</p> + <code type="none"> ets:select(emp_tab, ets:fun2ms( fun(#emp{empno = [$0 | Rest] }) -> {[$0|Rest],[$1|Rest]} - end)). </code> - <p>As a matter of fact, this query hits the feature of partially bound - keys in the table type <c>ordered_set</c>, so that not the whole - table need be searched, only the part of the table containing keys - beginning with <c>0</c> is in fact looked into. </p> - <p>The fun of course can have several clauses, so that if one could do - the following: For each employee, if he or she is hired prior to 1997, - return the tuple <c><![CDATA[{inventory, <employee number>}]]></c>, for each hired 1997 - or later, but before 2001, return <c><![CDATA[{rookie, <employee number>}]]></c>, for all others return <c><![CDATA[{newbie, <employee number>}]]></c>. All except for the ones named <c>Smith</c> as - they would be affronted by anything other than the tag - <c>guru</c> and that is also what's returned for their numbers; - <c><![CDATA[{guru, <employee number>}]]></c>:</p> + end)).</code> + + <p>This query hits the feature of partially bound + keys in table type <c>ordered_set</c>, so that not the whole + table needs to be searched, only the part containing keys + beginning with <c>0</c> is looked into.</p> + </section> + + <section> + <title>Example 5</title> + <p>The fun can have many clauses. Assume that we want to do + the following:</p> + + <list type="bulleted"> + <item> + <p>If an employee started before 1997, return the tuple + <c><![CDATA[{inventory, <employee number>}]]></c>.</p> + </item> + <item> + <p>If an employee started 1997 or later, but before 2001, return + <c><![CDATA[{rookie, <employee number>}]]></c>.</p> + </item> + <item> + <p>For all other employees, return + <c><![CDATA[{newbie, <employee number>}]]></c>, except for those + named <c>Smith</c> as they would be affronted by anything other + than the tag <c>guru</c> and that is also what is returned for their + numbers: <c><![CDATA[{guru, <employee number>}]]></c>.</p> + </item> + </list> + + <p>This is accomplished as follows:</p> + <code type="none"><![CDATA[ ets:select(emp_tab, ets:fun2ms( fun(#emp{empno = E, surname = "Smith" }) -> @@ -267,7 +321,9 @@ ets:select(emp_tab, ets:fun2ms( (#emp{empno = E, empyear = Y}) -> % 1997 -- 2001 {rookie, E} end)). ]]></code> - <p>The result will be:</p> + + <p>The result is as follows:</p> + <code type="none"> [{rookie,"011103"}, {rookie,"041231"}, @@ -277,162 +333,207 @@ ets:select(emp_tab, ets:fun2ms( {rookie,"535216"}, {inventory,"789789"}, {newbie,"963721"}, - {rookie,"989891"}] </code> - <p>and so the Smith's will be happy...</p> - <p>So, what more can you do? Well, the simple answer would be; look - in the documentation of match specifications in ERTS users - guide. However let's briefly go through the most useful "built in - functions" that you can use when the <c>fun</c> is to be - translated into a match specification by <c>ets:fun2ms</c> (it's - worth mentioning, although it might be obvious to some, that calling - other functions than the one's allowed in match specifications cannot - be done. No "usual" Erlang code can be executed by the <c>fun</c> being - translated by <c>fun2ms</c>, the <c>fun</c> is after all limited + {rookie,"989891"}]</code> + </section> + + <section> + <title>Useful BIFs</title> + <p>What more can you do? A simple answer is: see the documentation of + <seealso marker="erts:match_spec">match specifications</seealso> + in ERTS User's Guide. + However, the following is a brief overview of the most useful "built-in + functions" that you can use when the fun is to be translated into a match + specification by + <seealso marker="ets#fun2ms/1"> <c>ets:fun2ms/1</c></seealso>. It is not + possible to call other functions than those allowed in match + specifications. No "usual" Erlang code can be executed by the fun that + is translated by <c>ets:fun2ms/1</c>. The fun is limited exactly to the power of the match specifications, which is - unfortunate, but the price one has to pay for the execution speed of - an <c>ets:select</c> compared to <c>ets:foldl/foldr</c>).</p> - <p>The head of the <c>fun</c> is obviously a head matching (or mismatching) - <em>one</em> parameter, one object of the table we <c>select</c> + unfortunate, but the price one must pay for the execution speed of + <c>ets:select/2</c> compared to <c>ets:foldl/foldr</c>.</p> + + <p>The head of the fun is a head matching (or mismatching) + <em>one</em> parameter, one object of the table we select from. The object is always a single variable (can be <c>_</c>) or - a tuple, as that's what's in <c>ets, dets</c> and - <c>mnesia</c> tables (the match specification returned by - <c>ets:fun2ms</c> can of course be used with - <c>dets:select</c> and <c>mnesia:select</c> as well as - with <c>ets:select</c>). The use of <c>=</c> in the head - is allowed (and encouraged) on the top level.</p> + a tuple, as ETS, Dets, and Mnesia tables include + that. The match specification returned by <c>ets:fun2ms/1</c> can + be used with <c>dets:select/2</c> and <c>mnesia:select/2</c>, and + with <c>ets:select/2</c>. The use of <c>=</c> in the head + is allowed (and encouraged) at the top-level.</p> + <p>The guard section can contain any guard expression of Erlang. - Even the "old" type test are allowed on the toplevel of the guard - (<c>integer(X)</c> instead of <c>is_integer(X)</c>). As the new type tests (the - <c>is_</c> tests) are in practice just guard bif's they can also - be called from within the body of the fun, but so they can in ordinary - Erlang code. Also arithmetics is allowed, as well as ordinary guard - bif's. Here's a list of bif's and expressions:</p> + The following is a list of BIFs and expressions:</p> + <list type="bulleted"> - <item>The type tests: is_atom, is_float, is_integer, - is_list, is_number, is_pid, is_port, is_reference, is_tuple, - is_binary, is_function, is_record</item> - <item>The boolean operators: not, and, or, andalso, orelse </item> - <item>The relational operators: >, >=, <, =<, =:=, ==, =/=, /=</item> - <item>Arithmetics: +, -, *, div, rem</item> - <item>Bitwise operators: band, bor, bxor, bnot, bsl, bsr</item> - <item>The guard bif's: abs, element, hd, length, node, round, size, tl, - trunc, self</item> - <item>The obsolete type test (only in guards): - atom, float, integer, - list, number, pid, port, reference, tuple, - binary, function, record</item> + <item> + <p>Type tests: <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_binary</c>, + <c>is_function</c>, <c>is_record</c></p> + </item> + <item> + <p>Boolean operators: <c>not</c>, <c>and</c>, <c>or</c>, + <c>andalso</c>, <c>orelse</c></p> + </item> + <item> + <p>Relational operators: >, >=, <, =<, =:=, ==, =/=, /=</p> + </item> + <item> + <p>Arithmetics: <c>+</c>, <c>-</c>, <c>*</c>, + <c>div</c>, <c>rem</c></p> + </item> + <item> + <p>Bitwise operators: <c>band</c>, <c>bor</c>, <c>bxor</c>, <c>bnot</c>, + <c>bsl</c>, <c>bsr</c></p> + </item> + <item> + <p>The guard BIFs: <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>self</c></p> + </item> </list> + <p>Contrary to the fact with "handwritten" match specifications, the <c>is_record</c> guard works as in ordinary Erlang code.</p> - <p>Semicolons (<c>;</c>) in guards are allowed, the result will be (as - expected) one "match_spec-clause" for each semicolon-separated - part of the guard. The semantics being identical to the Erlang + + <p>Semicolons (<c>;</c>) in guards are allowed, the result is (as + expected) one "match specification clause" for each semicolon-separated + part of the guard. The semantics is identical to the Erlang semantics.</p> - <p>The body of the <c>fun</c> is used to construct the - resulting value. When selecting from tables one usually just construct + + <p>The body of the fun is used to construct the + resulting value. When selecting from tables, one usually construct a suiting term here, using ordinary Erlang term construction, like - tuple parentheses, list brackets and variables matched out in the - head, possibly in conjunction with the occasional constant. Whatever - expressions are allowed in guards are also allowed here, but there are - no special functions except <c>object</c> and + tuple parentheses, list brackets, and variables matched out in the + head, possibly with the occasional constant. Whatever + expressions are allowed in guards are also allowed here, but no special + functions exist except <c>object</c> and <c>bindings</c> (see further down), which returns the whole - matched object and all known variable bindings respectively.</p> + matched object and all known variable bindings, respectively.</p> + <p>The <c>dbg</c> variants of match specifications have an - imperative approach to the match specification body, the ets dialect - hasn't. The fun body for <c>ets:fun2ms</c> returns the result - without side effects, and as matching (<c>=</c>) in the body of + imperative approach to the match specification body, the ETS + dialect has not. The fun body for <c>ets:fun2ms/1</c> returns the result + without side effects. As matching (<c>=</c>) in the body of the match specifications is not allowed (for performance reasons) the - only thing left, more or less, is term construction...</p> - <p>Let's move on to the <c>dbg</c> dialect, the slightly - different match specifications translated by <c>dbg:fun2ms</c>. </p> - <p>The same reasons for using the parse transformation applies to - <c>dbg</c>, maybe even more so as filtering using Erlang code is - simply not a good idea when tracing (except afterwards, if you trace - to file). The concept is similar to that of <c>ets:fun2ms</c> - except that you usually use it directly from the shell (which can also - be done with <c>ets:fun2ms</c>). </p> - <p>Let's manufacture a toy module to trace on </p> + only thing left, more or less, is term construction.</p> + </section> + + <section> + <title>Example with dbg</title> + <p>This section describes the slightly different match specifications + translated by <seealso marker="runtime_tools:dbg#fun2ms/1"> + <c>dbg:fun2ms/1</c></seealso>.</p> + + <p>The same reasons for using the parse transformation apply to + <c>dbg</c>, maybe even more, as filtering using Erlang code is + not a good idea when tracing (except afterwards, if you trace + to file). The concept is similar to that of <c>ets:fun2ms/1</c> + except that you usually use it directly from the shell + (which can also be done with <c>ets:fun2ms/1</c>).</p> + + <p>The following is an example module to trace on:</p> + <code type="none"> -module(toy). -export([start/1, store/2, retrieve/1]). start(Args) -> - toy_table = ets:new(toy_table,Args). + toy_table = ets:new(toy_table, Args). store(Key, Value) -> - ets:insert(toy_table,{Key,Value}). + ets:insert(toy_table, {Key,Value}). retrieve(Key) -> - [{Key, Value}] = ets:lookup(toy_table,Key), - Value. </code> - <p>During model testing, the first test bails out with a + [{Key, Value}] = ets:lookup(toy_table, Key), + Value.</code> + + <p>During model testing, the first test results in <c>{badmatch,16}</c> in <c>{toy,start,1}</c>, why?</p> - <p>We suspect the ets call, as we match hard on the return value, but - want only the particular <c>new</c> call with - <c>toy_table</c> as first parameter. - So we start a default tracer on the node:</p> + + <p>We suspect the <c>ets:new/2</c> call, as we match hard on the + return value, but want only the particular <c>new/2</c> call with + <c>toy_table</c> as first parameter. So we start a default tracer + on the node:</p> + <pre> 1> <input>dbg:tracer().</input> {ok,<0.88.0>}</pre> - <p>And so we turn on call tracing for all processes, we are going to - make a pretty restrictive trace pattern, so there's no need to call - trace only a few processes (it usually isn't):</p> + + <p>We turn on call tracing for all processes, we want to + make a pretty restrictive trace pattern, so there is no need to call + trace only a few processes (usually it is not):</p> + <pre> 2> <input>dbg:p(all,call).</input> -{ok,[{matched,nonode@nohost,25}]} </pre> - <p>It's time to specify the filter. We want to view calls that resemble - <c><![CDATA[ets:new(toy_table,<something>)]]></c>:</p> +{ok,[{matched,nonode@nohost,25}]}</pre> + + <p>We specify the filter, we want to view calls that resemble + <c><![CDATA[ets:new(toy_table, <something>)]]></c>:</p> + <pre> 3> <input>dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> true end)).</input> -{ok,[{matched,nonode@nohost,1},{saved,1}]} </pre> - <p>As can be seen, the <c>fun</c>'s used with - <c>dbg:fun2ms</c> takes a single list as parameter instead of a +{ok,[{matched,nonode@nohost,1},{saved,1}]}</pre> + + <p>As can be seen, the fun used with + <c>dbg:fun2ms/1</c> takes a single list as parameter instead of a single tuple. The list matches a list of the parameters to the traced - function. A single variable may also be used of course. The body - of the fun expresses in a more imperative way actions to be taken if - the fun head (and the guards) matches. I return <c>true</c> here, but it's - only because the body of a fun cannot be empty, the return value will - be discarded. </p> - <p>When we run the test of our module now, we get the following trace - output:</p> + function. A single variable can also be used. The body + of the fun expresses, in a more imperative way, actions to be taken if + the fun head (and the guards) matches. <c>true</c> is returned here, + only because the body of a fun cannot be empty. The return value + is discarded.</p> + + <p>The following trace output is received during test:</p> + <code type="none"><![CDATA[ -(<0.86.0>) call ets:new(toy_table,[ordered_set]) ]]></code> - <p>Let's play we haven't spotted the problem yet, and want to see what - <c>ets:new</c> returns. We do a slightly different trace - pattern:</p> +(<0.86.0>) call ets:new(toy_table, [ordered_set]) ]]></code> + + <p>Assume that we have not found the problem yet, and want to see what + <c>ets:new/2</c> returns. We use a slightly different trace pattern:</p> + <pre> 4> <input>dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> return_trace() end)).</input></pre> - <p>Resulting in the following trace output when we run the test:</p> + + <p>The following trace output is received during test:</p> + <code type="none"><![CDATA[ (<0.86.0>) call ets:new(toy_table,[ordered_set]) (<0.86.0>) returned from ets:new/2 -> 24 ]]></code> - <p>The call to <c>return_trace</c>, makes a trace message appear + + <p>The call to <c>return_trace</c> results in a trace message when the function returns. It applies only to the specific function call triggering the match specification (and matching the head/guards of - the match specification). This is the by far the most common call in the + the match specification). This is by far the most common call in the body of a <c>dbg</c> match specification.</p> - <p>As the test now fails with <c>{badmatch,24}</c>, it's obvious - that the badmatch is because the atom <c>toy_table</c> does not - match the number returned for an unnamed table. So we spotted the - problem, the table should be named and the arguments supplied by our - test program does not include <c>named_table</c>. We rewrite the - start function to:</p> + + <p>The test now fails with <c>{badmatch,24}</c> because the atom + <c>toy_table</c> does not match the number returned for an unnamed table. + So, the problem is found, the table is to be named, and the arguments + supplied by the test program do not include <c>named_table</c>. We + rewrite the start function:</p> + <code type="none"> start(Args) -> - toy_table = ets:new(toy_table,[named_table |Args]). </code> - <p>And with the same tracing turned on, we get the following trace - output:</p> + toy_table = ets:new(toy_table, [named_table|Args]).</code> + + <p>With the same tracing turned on, the following trace output is + received:</p> + <code type="none"><![CDATA[ (<0.86.0>) call ets:new(toy_table,[named_table,ordered_set]) (<0.86.0>) returned from ets:new/2 -> toy_table ]]></code> - <p>Very well. Let's say the module now passes all testing and goes into - the system. After a while someone realizes that the table - <c>toy_table</c> grows while the system is running and that for some - reason there are a lot of elements with atom's as keys. You had - expected only integer keys and so does the rest of the system. Well, - obviously not all of the system. You turn on call tracing and try to - see calls to your module with an atom as the key:</p> + + <p>Assume that the module now passes all testing and goes into + the system. After a while, it is found that table + <c>toy_table</c> grows while the system is running and that + there are many elements with atoms as keys. We expected + only integer keys and so does the rest of the system, but + clearly not the entire system. We turn on call tracing and try to + see calls to the module with an atom as the key:</p> + <pre> 1> <input>dbg:tracer().</input> {ok,<0.88.0>} @@ -440,80 +541,101 @@ start(Args) -> {ok,[{matched,nonode@nohost,25}]} 3> <input>dbg:tpl(toy,store,dbg:fun2ms(fun([A,_]) when is_atom(A) -> true end)).</input> {ok,[{matched,nonode@nohost,1},{saved,1}]}</pre> - <p>We use <c>dbg:tpl</c> here to make sure to catch local calls - (let's say the module has grown since the smaller version and we're - not sure this inserting of atoms is not done locally...). When in - doubt always use local call tracing.</p> - <p>Let's say nothing happens when we trace in this way. Our function - is never called with these parameters. We make the conclusion that - someone else (some other module) is doing it and we realize that we - must trace on ets:insert and want to see the calling function. The - calling function may be retrieved using the match specification - function <c>caller</c> and to get it into the trace message, one - has to use the match spec function <c>message</c>. The filter - call looks like this (looking for calls to <c>ets:insert</c>):</p> + + <p>We use <c>dbg:tpl/3</c> to ensure to catch local calls + (assume that the module has grown since the smaller version and we are + unsure if this inserting of atoms is not done locally). When in + doubt, always use local call tracing.</p> + + <p>Assume that nothing happens when tracing in this way. The function + is never called with these parameters. We conclude that + someone else (some other module) is doing it and realize that we + must trace on <c>ets:insert/2</c> and want to see the calling function. + The calling function can be retrieved using the match specification + function <c>caller</c>. To get it into the trace message, the match + specification function <c>message</c> must be used. The filter + call looks like this (looking for calls to <c>ets:insert/2</c>):</p> + <pre> 4> <input>dbg:tpl(ets,insert,dbg:fun2ms(fun([toy_table,{A,_}]) when is_atom(A) -> </input> <input> message(caller()) </input> <input> end)). </input> -{ok,[{matched,nonode@nohost,1},{saved,2}]} </pre> - <p>The caller will now appear in the "additional message" part of the - trace output, and so after a while, the following output comes:</p> +{ok,[{matched,nonode@nohost,1},{saved,2}]}</pre> + + <p>The caller is now displayed in the "additional message" part of the + trace output, and the following is displayed after a while:</p> + <code type="none"><![CDATA[ (<0.86.0>) call ets:insert(toy_table,{garbage,can}) ({evil_mod,evil_fun,2}) ]]></code> - <p>You have found out that the function <c>evil_fun</c> of the - module <c>evil_mod</c>, with arity <c>2</c>, is the one - causing all this trouble.</p> - <p>This was just a toy example, but it illustrated the most used - calls in match specifications for <c>dbg</c> The other, more - esotheric calls are listed and explained in the <em>Users guide of the ERTS application</em>, they really are beyond the scope of this - document.</p> - <p>To end this chatty introduction with something more precise, here - follows some parts about caveats and restrictions concerning the fun's - used in conjunction with <c>ets:fun2ms</c> and - <c>dbg:fun2ms</c>:</p> + + <p>You have realized that function <c>evil_fun</c> of the + <c>evil_mod</c> module, with arity <c>2</c>, is causing all this trouble. + </p> + + <p>This example illustrates the most used calls in match specifications for + <c>dbg</c>. The other, more esoteric, calls are listed and explained in + <seealso marker="erts:match_spec">Match specifications in Erlang</seealso> + in ERTS User's Guide, as they are beyond + the scope of this description.</p> + </section> + + <section> + <title>Warnings and Restrictions</title> + <marker id="warnings_and_restrictions"/> + <p>The following warnings and restrictions apply to the funs used in + with <c>ets:fun2ms/1</c> and <c>dbg:fun2ms/1</c>.</p> + <warning> - <p>To use the pseudo functions triggering the translation, one - <em>has to</em> include the header file <c>ms_transform.hrl</c> - in the source code. Failure to do so will possibly result in - runtime errors rather than compile time, as the expression may + <p>To use the pseudo functions triggering the translation, + ensure to include the header file <c>ms_transform.hrl</c> + in the source code. Failure to do so possibly results in + runtime errors rather than compile time, as the expression can be valid as a plain Erlang program without translation.</p> </warning> + <warning> - <p>The <c>fun</c> has to be literally constructed inside the - parameter list to the pseudo functions. The <c>fun</c> cannot + <p>The fun must be literally constructed inside the + parameter list to the pseudo functions. The fun cannot be bound to a variable first and then passed to - <c>ets:fun2ms</c> or <c>dbg:fun2ms</c>, i.e this - will work: <c>ets:fun2ms(fun(A) -> A end)</c> but not this: - <c>F = fun(A) -> A end, ets:fun2ms(F)</c>. The later will result - in a compile time error if the header is included, otherwise a - runtime error. Even if the later construction would ever - appear to work, it really doesn't, so don't ever use it.</p> + <c>ets:fun2ms/1</c> or <c>dbg:fun2ms/1</c>. For example, + <c>ets:fun2ms(fun(A) -> A end)</c> works, but not + <c>F = fun(A) -> A end, ets:fun2ms(F)</c>. The latter results + in a compile-time error if the header is included, otherwise a + runtime error.</p> </warning> - <p>Several restrictions apply to the fun that is being translated - into a match_spec. To put it simple you cannot use anything in - the fun that you cannot use in a match_spec. This means that, + + <p>Many restrictions apply to the fun that is translated into a match + specification. To put it simple: you cannot use anything in the fun + that you cannot use in a match specification. This means that, among others, the following restrictions apply to the fun itself:</p> + <list type="bulleted"> - <item>Functions written in Erlang cannot be called, neither - local functions, global functions or real fun's</item> - <item>Everything that is written as a function call will be - translated into a match_spec call to a builtin function, so that - the call <c>is_list(X)</c> will be translated to <c>{'is_list', '$1'}</c> (<c>'$1'</c> is just an example, the numbering may - vary). If one tries to call a function that is not a match_spec - builtin, it will cause an error.</item> - <item>Variables occurring in the head of the <c>fun</c> will be - replaced by match_spec variables in the order of occurrence, so - that the fragment <c>fun({A,B,C})</c> will be replaced by - <c>{'$1', '$2', '$3'}</c> etc. Every occurrence of such a - variable later in the match_spec will be replaced by a - match_spec variable in the same way, so that the fun - <c>fun({A,B}) when is_atom(A) -> B end</c> will be translated into - <c>[{{'$1','$2'},[{is_atom,'$1'}],['$2']}]</c>.</item> <item> - <p>Variables that are not appearing in the head are imported - from the environment and made into - match_spec <c>const</c> expressions. Example from the shell:</p> + <p>Functions written in Erlang cannot be called, neither can + local functions, global functions, or real funs.</p> + </item> + <item> + <p>Everything that is written as a function call is translated + into a match specification call to a built-in function, so that + the call <c>is_list(X)</c> is translated to <c>{'is_list', '$1'}</c> + (<c>'$1'</c> is only an example, the numbering can vary). + If one tries to call a function that is not a match specification + built-in, it causes an error.</p> + </item> + <item> + <p>Variables occurring in the head of the fun are replaced by + match specification variables in the order of occurrence, so + that fragment <c>fun({A,B,C})</c> is replaced by + <c>{'$1', '$2', '$3'}</c>, and so on. Every occurrence of such a + variable in the match specification is replaced by a match + specification variable in the same way, so that the fun + <c>fun({A,B}) when is_atom(A) -> B end</c> is translated into + <c>[{{'$1','$2'},[{is_atom,'$1'}],['$2']}]</c>.</p> + </item> + <item> + <p>Variables that are not included in the head are imported + from the environment and made into match specification + <c>const</c> expressions. Example from the shell:</p> <pre> 1> <input>X = 25.</input> 25 @@ -522,7 +644,7 @@ start(Args) -> </item> <item> <p>Matching with <c>=</c> cannot be used in the body. It can only - be used on the top level in the head of the fun. + be used on the top-level in the head of the fun. Example from the shell again:</p> <pre> 1> <input>ets:fun2ms(fun({A,[B|C]} = D) when A > B -> D end).</input> @@ -533,106 +655,125 @@ match_spec {error,transform_error} 3> <input>ets:fun2ms(fun({A,[B|C]}) when A > B -> D = [B|C], D end).</input> Error: fun with body matching ('=' in body) is illegal as match_spec -{error,transform_error} </pre> - <p>All variables are bound in the head of a match_spec, so the - translator can not allow multiple bindings. The special case - when matching is done on the top level makes the variable bind - to <c>'$_'</c> in the resulting match_spec, it is to allow a more - natural access to the whole matched object. The pseudo - function <c>object()</c> could be used instead, see below. - The following expressions are translated equally: </p> +{error,transform_error}</pre> + <p>All variables are bound in the head of a match specification, so + the translator cannot allow multiple bindings. The special case + when matching is done on the top-level makes the variable bind + to <c>'$_'</c> in the resulting match specification. It is to allow + a more natural access to the whole matched object. Pseudo + function <c>object()</c> can be used instead, see below.</p> + <p>The following expressions are translated equally:</p> <code type="none"> ets:fun2ms(fun({a,_} = A) -> A end). ets:fun2ms(fun({a,_}) -> object() end).</code> </item> <item> - <p>The special match_spec variables <c>'$_'</c> and <c>'$*'</c> + <p>The special match specification variables <c>'$_'</c> and <c>'$*'</c> can be accessed through the pseudo functions <c>object()</c> (for <c>'$_'</c>) and <c>bindings()</c> (for <c>'$*'</c>). - as an example, one could translate the following - <c>ets:match_object/2</c> call to a <c>ets:select</c> call:</p> + As an example, one can translate the following + <c>ets:match_object/2</c> call to a <c>ets:select/2</c> call:</p> <code type="none"> ets:match_object(Table, {'$1',test,'$2'}). </code> - <p>...is the same as...</p> + <p>This is the same as:</p> <code type="none"> ets:select(Table, ets:fun2ms(fun({A,test,B}) -> object() end)).</code> - <p>(This was just an example, in this simple case the former - expression is probably preferable in terms of readability). - The <c>ets:select/2</c> call will conceptually look like this + <p>In this simple case, the former + expression is probably preferable in terms of readability.</p> + <p>The <c>ets:select/2</c> call conceptually looks like this in the resulting code:</p> <code type="none"> ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).</code> - <p>Matching on the top level of the fun head might feel like a + <p>Matching on the top-level of the fun head can be a more natural way to access <c>'$_'</c>, see above.</p> </item> - <item>Term constructions/literals are translated as much as is - needed to get them into valid match_specs, so that tuples are - made into match_spec tuple constructions (a one element tuple - containing the tuple) and constant expressions are used when - importing variables from the environment. Records are also - translated into plain tuple constructions, calls to element - etc. The guard test <c>is_record/2</c> is translated into - match_spec code using the three parameter version that's built - into match_specs, so that <c>is_record(A,t)</c> is translated - into <c>{is_record,'$1',t,5}</c> given that the record size of - record type <c>t</c> is 5.</item> - <item>Language constructions like <c>case</c>, <c>if</c>, - <c>catch</c> etc that are not present in match_specs are not - allowed.</item> - <item>If the header file <c>ms_transform.hrl</c> is not included, - the fun won't be translated, which may result in a - <em>runtime error</em> (depending on if the fun is valid in a - pure Erlang context). Be absolutely sure that the header is - included when using <c>ets</c> and <c>dbg:fun2ms/1</c> in - compiled code.</item> - <item>If the pseudo function triggering the translation is - <c>ets:fun2ms/1</c>, the fun's head must contain a single - variable or a single tuple. If the pseudo function is - <c>dbg:fun2ms/1</c> the fun's head must contain a single - variable or a single list.</item> + <item> + <p>Term constructions/literals are translated as much as is needed to + get them into valid match specification. This way tuples are made + into match specification tuple constructions (a one element tuple + containing the tuple) and constant expressions are used when + importing variables from the environment. Records are also + translated into plain tuple constructions, calls to element, + and so on. The guard test <c>is_record/2</c> is translated into + match specification code using the three parameter version that is + built into match specification, so that <c>is_record(A,t)</c> is + translated into <c>{is_record,'$1',t,5}</c> if the record + size of record type <c>t</c> is 5.</p> + </item> + <item> + <p>Language constructions such as <c>case</c>, <c>if</c>, and + <c>catch</c> that are not present in match specifications are not + allowed.</p> + </item> + <item> + <p>If header file <c>ms_transform.hrl</c> is not included, + the fun is not translated, which can result in a + <em>runtime error</em> (depending on whether the fun is + valid in a pure Erlang context).</p> + <p>Ensure that the header is included when using <c>ets</c> and + <c>dbg:fun2ms/1</c> in compiled code.</p> + </item> + <item> + <p>If pseudo function triggering the translation is + <c>ets:fun2ms/1</c>, the head of the fun must contain a single + variable or a single tuple. If the pseudo function is + <c>dbg:fun2ms/1</c>, the head of the fun must contain a single + variable or a single list.</p> + </item> </list> - <p>The translation from fun's to match_specs is done at compile + <p>The translation from funs to match specifications is done at compile time, so runtime performance is not affected by using these pseudo - functions. The compile time might be somewhat longer though. </p> - <p>For more information about match_specs, please read about them - in <em>ERTS users guide</em>.</p> - </description> + functions.</p> + <p>For more information about match specifications, see the + <seealso marker="erts:match_spec">Match specifications in Erlang</seealso> + in ERTS User's Guide.</p> + </section> + <funcs> <func> - <name name="parse_transform" arity="2"/> - <fsummary>Transforms Erlang abstract format containing calls to ets/dbg:fun2ms into literal match specifications.</fsummary> - <type_desc variable="Options">Option list, required but not used.</type_desc> + <name name="format_error" arity="1"/> + <fsummary>Error formatting function as required by the parse transformation interface.</fsummary> <desc> - <p>Implements the actual transformation at compile time. This - function is called by the compiler to do the source code - transformation if and when the <c>ms_transform.hrl</c> header - file is included in your source code. See the <c>ets</c> and - <c>dbg</c>:<c>fun2ms/1</c> function manual pages for - documentation on how to use this parse_transform, see the - <c>match_spec</c> chapter in <c>ERTS</c> users guide for a - description of match specifications. </p> + <p>Takes an error code returned by one of the other functions + in the module and creates a textual description of the + error.</p> </desc> </func> + <func> - <name name="transform_from_shell" arity="3"/> - <fsummary>Used when transforming fun's created in the shell into match_specifications.</fsummary> - <type_desc variable="BoundEnvironment">List of variable bindings in the shell environment.</type_desc> + <name name="parse_transform" arity="2"/> + <fsummary>Transforms Erlang abstract format containing calls to + ets/dbg:fun2ms/1 into literal match specifications.</fsummary> + <type_desc variable="Options">Option list, required but not used. + </type_desc> <desc> - <p>Implements the actual transformation when the <c>fun2ms</c> - functions are called from the shell. In this case the abstract - form is for one single fun (parsed by the Erlang shell), and - all imported variables should be in the key-value list passed - as <c><anno>BoundEnvironment</anno></c>. The result is a term, normalized, - i.e. not in abstract format.</p> + <p>Implements the transformation at compile time. This + function is called by the compiler to do the source code + transformation if and when header file <c>ms_transform.hrl</c> + is included in the source code.</p> + <p>For information about how to use this parse transformation, see + <seealso marker="ets"><c>ets</c></seealso> and + <seealso marker="runtime_tools:dbg#fun2ms/1"> + <c>dbg:fun2ms/1</c></seealso>.</p> + <p>For a description of match specifications, see section + <seealso marker="erts:match_spec"> + Match Specification in Erlang</seealso> in ERTS User's Guide.</p> </desc> </func> + <func> - <name name="format_error" arity="1"/> - <fsummary>Error formatting function as required by the parse_transform interface.</fsummary> + <name name="transform_from_shell" arity="3"/> + <fsummary>Used when transforming funs created in the shell into + match_specifications.</fsummary> + <type_desc variable="BoundEnvironment">List of variable bindings in the + shell environment.</type_desc> <desc> - <p>Takes an error code returned by one of the other functions - in the module and creates a textual description of the - error. Fairly uninteresting function actually.</p> + <p>Implements the transformation when the <c>fun2ms/1</c> + functions are called from the shell. In this case, the abstract + form is for one single fun (parsed by the Erlang shell). + All imported variables are to be in the key-value list passed + as <c><anno>BoundEnvironment</anno></c>. The result is a term, + normalized, that is, not in abstract format.</p> </desc> </func> </funcs> |