Provided by: erlang-manpages_25.3.2.8+dfsg-1ubuntu4.4_all bug

NAME

       ms_transform - A parse transformation that translates fun syntax into match
           specifications.

DESCRIPTION

       This  module  provides  the  parse transformation that makes calls to ets and dbg:fun2ms/1 translate into
       literal match specifications. It also provides the back end for the same functions when called  from  the
       Erlang shell.

       The  translation  from  funs  to  match  specifications  is  accessed  through the two "pseudo functions"
       ets:fun2ms/1 and dbg:fun2ms/1.

       As everyone trying to use ets:select/2 or dbg seems to end up reading this manual page, this  description
       is an introduction to the concept of match specifications.

       Read the whole manual page if it is the first time you are using the transformations.

       Match  specifications  are  used  more  or less as filters. They resemble usual Erlang matching in a list
       comprehension or in a fun used with  lists:foldl/3,  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.

       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 translates the fun syntax into match specification
       terms.

EXAMPLE 1

       Using ets:select/2 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 ets:foldl/3 instead, but the
       ets:select/2 call is far more efficient. Without the  translation  provided  by  ms_transform,  one  must
       struggle with writing match specifications terms to accommodate this.

       Consider a simple table of employees:

       -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

       We create the table using:

       ets:new(emp_tab, [{keypos,#emp.empno},named_table,ordered_set]).

       We fill the table with randomly chosen data:

       [{emp,"011103","Black","Alfred",sales,2000},
        {emp,"041231","Doe","John",prod,2001},
        {emp,"052341","Smith","John",dev,1997},
        {emp,"076324","Smith","Ella",sales,1995},
        {emp,"122334","Weston","Anna",prod,2002},
        {emp,"535216","Chalker","Samuel",adm,1998},
        {emp,"789789","Harrysson","Joe",adm,1996},
        {emp,"963721","Scott","Juliana",dev,2003},
        {emp,"989891","Brown","Gabriel",prod,1999}]

       Assuming that we want the employee numbers of everyone in the sales department, there are several ways.

       ets:match/2 can be used:

       1> ets:match(emp_tab, {'_', '$1', '_', '_', sales, '_'}).
       [["011103"],["076324"]]

       ets:match/2  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.

       ets:foldl/3 or ets:foldr/3 can be used to avoid the nested lists:

       ets:foldr(fun(#emp{empno = E, dept = sales},Acc) -> [E | Acc];
                    (_,Acc) -> Acc
                 end,
                 [],
                 emp_tab).

       The result is ["011103","076324"]. The fun is straightforward, so the only problem is that all  the  data
       from  the  table  must  be  transferred  from  the  table  to  the calling process for filtering. That is
       inefficient compared to the ets:match/2 call where the filtering can be done "inside"  the  emulator  and
       only the result is transferred to the process.

       Consider a "pure" ets:select/2 call that does what ets:foldr does:

       ets:select(emp_tab, [{#emp{empno = '$1', dept = sales, _='_'},[],['$1']}]).

       Although  the record syntax is used, it is still hard to read and even harder to write. The first element
       of the tuple, #emp{empno = '$1', dept = sales, _='_'}, tells what to match. Elements  not  matching  this
       are  not  returned, as in the ets:match/2 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 is almost always a list containing one single term). In our case '$1' is bound to the
       employee number in the head (first element of the tuple), and hence the employee number is returned.  The
       result  is  ["011103","076324"],  as  in  the  ets:foldr/3 example, but the result is retrieved much more
       efficiently in terms of execution speed and memory consumption.

       Using ets:fun2ms/1, we can combine the ease of use of the ets:foldr/3 and  the  efficiency  of  the  pure
       ets:select/2 example:

       -include_lib("stdlib/include/ms_transform.hrl").

       ets:select(emp_tab, ets:fun2ms(
                             fun(#emp{empno = E, dept = sales}) ->
                                     E
                             end)).

       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 ets:foldr/3 example. It is easier to read than the ets:foldr/3 example,
       as the select call in itself discards anything that does not match, while the fun of the ets:foldr/3 call
       needs to handle both the elements matching and the ones not matching.

       In the ets:fun2ms/1 example above, it is needed to include ms_transform.hrl in the source code,  as  this
       is  what  triggers the parse transformation of the ets:fun2ms/1 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.

EXAMPLE 2

       Assume  that  we  want  to  get  all  the  employee  numbers  of  employees hired before year 2000. Using
       ets:match/2 is not an alternative here, as relational operators cannot be expressed  there.  Once  again,
       ets:foldr/3 can do it (slowly, but correct):

       ets:foldr(fun(#emp{empno = E, empyear = Y},Acc) when Y < 2000 -> [E | Acc];
                         (_,Acc) -> Acc
                 end,
                 [],
                 emp_tab).

       The  result  is  ["052341","076324","535216","789789","989891"],  as  expected. The equivalent expression
       using a handwritten match specification would look like this:

       ets:select(emp_tab, [{#emp{empno = '$1', empyear = '$2', _='_'},
                            [{'<', '$2', 2000}],
                            ['$1']}]).

       This gives the same result. [{'<', '$2', 2000}] is in the guard part and therefore discards anything that
       does not have an empyear (bound to '$2' in the head) less than 2000, as the guard in the foldr/3 example.

       We write it using ets:fun2ms/1:

       -include_lib("stdlib/include/ms_transform.hrl").

       ets:select(emp_tab, ets:fun2ms(
                             fun(#emp{empno = E, empyear = Y}) when Y < 2000 ->
                                  E
                             end)).

EXAMPLE 3

       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:

       ets:select(emp_tab, ets:fun2ms(
                             fun(Obj = #emp{empno = E, empyear = Y})
                                when Y < 2000 ->
                                     Obj
                             end)).

       As in ordinary Erlang matching, you can bind a variable to the whole matched object using a "match inside
       the match", that is, a =. Unfortunately in funs translated to match specifications, it is allowed only at
       the "top-level", that is, matching the whole 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 object/0 also returns the whole  matched  object,  see  section
       Warnings and Restrictions.

EXAMPLE 4

       This  example concerns the body of the fun. Assume that all employee numbers beginning with zero (0) must
       be changed to begin with one (1) instead, and  that  we  want  to  create  the  list  [{<Old  empno>,<New
       empno>}]:

       ets:select(emp_tab, ets:fun2ms(
                             fun(#emp{empno = [$0 | Rest] }) ->
                                     {[$0|Rest],[$1|Rest]}
                             end)).

       This  query  hits  the  feature  of partially bound keys in table type ordered_set, so that not the whole
       table needs to be searched, only the part containing keys beginning with 0 is looked into.

EXAMPLE 5

       The fun can have many clauses. Assume that we want to do the following:

         * If an employee started before 1997, return the tuple {inventory, <employee number>}.

         * If an employee started 1997 or later, but before 2001, return {rookie, <employee number>}.

         * For all other employees, return {newbie, <employee number>}, except for those  named  Smith  as  they
           would  be  affronted  by anything other than the tag guru and that is also what is returned for their
           numbers: {guru, <employee number>}.

       This is accomplished as follows:

       ets:select(emp_tab, ets:fun2ms(
                             fun(#emp{empno = E, surname = "Smith" }) ->
                                     {guru,E};
                                (#emp{empno = E, empyear = Y}) when Y < 1997  ->
                                     {inventory, E};
                                (#emp{empno = E, empyear = Y}) when Y > 2001  ->
                                     {newbie, E};
                                (#emp{empno = E, empyear = Y}) -> % 1997 -- 2001
                                     {rookie, E}
                             end)).

       The result is as follows:

       [{rookie,"011103"},
        {rookie,"041231"},
        {guru,"052341"},
        {guru,"076324"},
        {newbie,"122334"},
        {rookie,"535216"},
        {inventory,"789789"},
        {newbie,"963721"},
        {rookie,"989891"}]

USEFUL BIFS

       What more can you do? A simple answer is: see the documentation of match specifications  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 ets:fun2ms/1. 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 ets:fun2ms/1. The fun is limited exactly  to  the  power  of  the  match
       specifications,  which is unfortunate, but the price one must pay for the execution speed of ets:select/2
       compared to ets:foldl/foldr.

       The head of the fun is a head matching (or mismatching) one parameter, one object of the table we  select
       from.  The  object  is  always  a  single variable (can be _) or a tuple, as ETS, Dets, and Mnesia tables
       include that. The match specification returned  by  ets:fun2ms/1  can  be  used  with  dets:select/2  and
       mnesia:select/2,  and with ets:select/2. The use of = in the head is allowed (and encouraged) at the top-
       level.

       The guard section can contain any guard expression of Erlang.  The  following  is  a  list  of  BIFs  and
       expressions:

         * 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

         * Boolean operators: not, and, or, andalso, orelse

         * Relational operators: >, >=, <, =<, =:=, ==, =/=, /=

         * Arithmetics: +, -, *, div, rem

         * Bitwise operators: band, bor, bxor, bnot, bsl, bsr

         * The guard BIFs: abs, element, hd, length, node, round, size, byte_size, tl, trunc, binary_part, self

       Contrary to the fact with "handwritten" match specifications, the is_record guard works  as  in  ordinary
       Erlang code.

       Semicolons  (;)  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.

       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  with  the  occasional  constant.  Whatever
       expressions are allowed in guards are also allowed here, but no special functions exist except object and
       bindings  (see  further  down),  which  returns the whole matched object and all known variable bindings,
       respectively.

       The dbg variants of match specifications have an imperative approach to the match specification body, the
       ETS dialect has not. The fun body for ets:fun2ms/1 returns the result without side effects.  As  matching
       (=) in the body of the match specifications is not allowed (for performance reasons) the only thing left,
       more or less, is term construction.

EXAMPLE WITH DBG

       This section describes the slightly different match specifications translated by dbg:fun2ms/1.

       The  same  reasons  for  using the parse transformation apply to dbg, 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 ets:fun2ms/1 except that you usually use it directly from the shell (which can also be
       done with ets:fun2ms/1).

       The following is an example module to trace on:

       -module(toy).

       -export([start/1, store/2, retrieve/1]).

       start(Args) ->
           toy_table = ets:new(toy_table, Args).

       store(Key, Value) ->
           ets:insert(toy_table, {Key,Value}).

       retrieve(Key) ->
           [{Key, Value}] = ets:lookup(toy_table, Key),
           Value.

       During model testing, the first test results in {badmatch,16} in {toy,start,1}, why?

       We  suspect  the ets:new/2 call, as we match hard on the return value, but want only the particular new/2
       call with toy_table as first parameter. So we start a default tracer on the node:

       1> dbg:tracer().
       {ok,<0.88.0>}

       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):

       2> dbg:p(all,call).
       {ok,[{matched,nonode@nohost,25}]}

       We specify the filter, we want to view calls that resemble ets:new(toy_table, <something>):

       3> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> true end)).
       {ok,[{matched,nonode@nohost,1},{saved,1}]}

       As  can  be  seen,  the  fun  used with dbg:fun2ms/1 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  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. true is returned here, only because the body of a fun cannot be  empty.  The  return
       value is discarded.

       The following trace output is received during test:

       (<0.86.0>) call ets:new(toy_table, [ordered_set])

       Assume  that we have not found the problem yet, and want to see what ets:new/2 returns. We use a slightly
       different trace pattern:

       4> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> return_trace() end)).

       The following trace output is received during test:

       (<0.86.0>) call ets:new(toy_table,[ordered_set])
       (<0.86.0>) returned from ets:new/2 -> 24

       The call to return_trace 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 by far the most common call in the body of a dbg match specification.

       The test now fails with {badmatch,24} because the atom toy_table 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 named_table. We rewrite the start function:

       start(Args) ->
           toy_table = ets:new(toy_table, [named_table|Args]).

       With the same tracing turned on, the following trace output is received:

       (<0.86.0>) call ets:new(toy_table,[named_table,ordered_set])
       (<0.86.0>) returned from ets:new/2 -> toy_table

       Assume that the module now passes all testing and goes into the system. After a while, it is  found  that
       table toy_table 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:

       1> dbg:tracer().
       {ok,<0.88.0>}
       2> dbg:p(all,call).
       {ok,[{matched,nonode@nohost,25}]}
       3> dbg:tpl(toy,store,dbg:fun2ms(fun([A,_]) when is_atom(A) -> true end)).
       {ok,[{matched,nonode@nohost,1},{saved,1}]}

       We  use  dbg:tpl/3  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.

       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
       ets:insert/2 and want to see the calling function. The calling function can be retrieved using the  match
       specification function caller. To get it into the trace message, the match specification function message
       must be used. The filter call looks like this (looking for calls to ets:insert/2):

       4> dbg:tpl(ets,insert,dbg:fun2ms(fun([toy_table,{A,_}]) when is_atom(A) ->
        message(caller())
        end)).
       {ok,[{matched,nonode@nohost,1},{saved,2}]}

       The  caller  is  now displayed in the "additional message" part of the trace output, and the following is
       displayed after a while:

       (<0.86.0>) call ets:insert(toy_table,{garbage,can}) ({evil_mod,evil_fun,2})

       You have realized that function evil_fun of the evil_mod module,  with  arity  2,  is  causing  all  this
       trouble.

       This  example  illustrates the most used calls in match specifications for dbg. The other, more esoteric,
       calls are listed and explained in Match specifications in Erlang in ERTS User's Guide, as they are beyond
       the scope of this description.

WARNINGS AND RESTRICTIONS

       The following warnings and restrictions apply to the funs used in with ets:fun2ms/1 and dbg:fun2ms/1.

   Warning:
       To  use  the  pseudo  functions  triggering  the  translation,  ensure  to  include   the   header   file
       ms_transform.hrl  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.

   Warning:
       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  ets:fun2ms/1  or  dbg:fun2ms/1.  For  example,
       ets:fun2ms(fun(A) -> A end) works, but not F = fun(A) -> A end, ets:fun2ms(F). The latter  results  in  a
       compile-time error if the header is included, otherwise a runtime error.

       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:

         * Functions  written in Erlang cannot be called, neither can local functions, global functions, or real
           funs.

         * Everything that is written as a function call is translated into a  match  specification  call  to  a
           built-in  function,  so  that the call is_list(X) is translated to {'is_list', '$1'} ('$1' 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.

         * Variables occurring in the head of the fun are replaced by match specification variables in the order
           of  occurrence,  so  that  fragment  fun({A,B,C}) is replaced by {'$1', '$2', '$3'}, 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 fun({A,B}) when is_atom(A) -> B end is translated into
           [{{'$1','$2'},[{is_atom,'$1'}],['$2']}].

         * Variables that are not included in the head are imported from the environment  and  made  into  match
           specification const expressions. Example from the shell:

         1> X = 25.
         25
         2> ets:fun2ms(fun({A,B}) when A > X -> B end).
         [{{'$1','$2'},[{'>','$1',{const,25}}],['$2']}]

         * Matching  with  = cannot be used in the body. It can only be used on the top-level in the head of the
           fun. Example from the shell again:

         1> ets:fun2ms(fun({A,[B|C]} = D) when A > B -> D end).
         [{{'$1',['$2'|'$3']},[{'>','$1','$2'}],['$_']}]
         2> ets:fun2ms(fun({A,[B|C]=D}) when A > B -> D end).
         Error: fun with head matching ('=' in head) cannot be translated into
         match_spec
         {error,transform_error}
         3> ets:fun2ms(fun({A,[B|C]}) when A > B -> D = [B|C], D end).
         Error: fun with body matching ('=' in body) is illegal as match_spec
         {error,transform_error}

           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 '$_'  in
           the  resulting match specification. It is to allow a more natural access to the whole matched object.
           Pseudo function object() can be used instead, see below.

           The following expressions are translated equally:

         ets:fun2ms(fun({a,_} = A) -> A end).
         ets:fun2ms(fun({a,_}) -> object() end).

         * The special match specification variables '$_' and '$*' can be accessed through the pseudo  functions
           object()  (for  '$_')  and  bindings()  (for  '$*').  As  an example, one can translate the following
           ets:match_object/2 call to a ets:select/2 call:

         ets:match_object(Table, {'$1',test,'$2'}).

           This is the same as:

         ets:select(Table, ets:fun2ms(fun({A,test,B}) -> object() end)).

           In this simple case, the former expression is probably preferable in terms of readability.

           The ets:select/2 call conceptually looks like this in the resulting code:

         ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).

           Matching on the top-level of the fun head can be a more natural way to access '$_', see above.

         * 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  is_record/2  is  translated into match specification code using the three parameter
           version  that  is  built  into  match  specification,  so  that  is_record(A,t)  is  translated  into
           {is_record,'$1',t,5} if the record size of record type t is 5.

         * Language  constructions  such as case, if, and catch that are not present in match specifications are
           not allowed.

         * If header file ms_transform.hrl is not included, the fun is not translated, which  can  result  in  a
           runtime error (depending on whether the fun is valid in a pure Erlang context).

           Ensure that the header is included when using ets and dbg:fun2ms/1 in compiled code.

         * If  pseudo  function  triggering  the translation is ets:fun2ms/1, the head of the fun must contain a
           single variable or a single tuple. If the pseudo function is dbg:fun2ms/1, the head of the  fun  must
           contain a single variable or a single list.

       The  translation from funs to match specifications is done at compile time, so runtime performance is not
       affected by using these pseudo functions.

       For more information about match specifications, see the Match specifications in Erlang  in  ERTS  User's
       Guide.

EXPORTS

       format_error(Error) -> Chars

              Types:

                 Error = {error, module(), term()}
                 Chars = io_lib:chars()

              Takes  an  error  code  returned by one of the other functions in the module and creates a textual
              description of the error.

       parse_transform(Forms, Options) -> Forms2 | Errors | Warnings

              Types:

                 Forms = Forms2 = [erl_parse:abstract_form() | erl_parse:form_info()]
                 Options = term()
                   Option list, required but not used.
                 Errors = {error, ErrInfo :: [tuple()], WarnInfo :: []}
                 Warnings = {warning, Forms2, WarnInfo :: [tuple()]}

              Implements the transformation at compile time. This function is called by the compiler to  do  the
              source  code  transformation  if  and  when header file ms_transform.hrl is included in the source
              code.

              For information about how to use this parse transformation, see ets and dbg:fun2ms/1.

              For a description of match specifications, see section  Match  Specification  in  Erlang  in  ERTS
              User's Guide.

       transform_from_shell(Dialect, Clauses, BoundEnvironment) -> term()

              Types:

                 Dialect = ets | dbg
                 Clauses = [erl_parse:abstract_clause()]
                 BoundEnvironment = erl_eval:binding_struct()
                   List of variable bindings in the shell environment.

              Implements the transformation when the fun2ms/1 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 BoundEnvironment. The result is a term, normalized, that is,
              not in abstract format.

Ericsson AB                                      stdlib 4.3.1.3                               ms_transform(3erl)