Module exprecs

Parse transform for generating record access functions.

Authors: : Ulf Wiger (ulf.wiger@ericsson.com).

Description

Parse transform for generating record access functions

This parse transform can be used to reduce compile-time dependencies in large systems.

In the old days, before records, Erlang programmers often wrote access functions for tuple data. This was tedious and error-prone. The record syntax made this easier, but since records were implemented fully in the pre-processor, a nasty compile-time dependency was introduced.

This module automates the generation of access functions for records. While this method cannot fully replace the utility of pattern matching, it does allow a fair bit of functionality on records without the need for compile-time dependencies.

Whenever record definitions need to be exported from a module, inserting a compiler attribute, export_records([RecName|...]) causes this transform to lay out access functions for the exported records:

   -record(a, {a, b, c}).
   -export_records([a]).
   -export(['#info-'/2,
            '#get-'/2, '#set-'/2,
            '#new-a'/0, '#new-a'/1,
            '#get-a'/2, '#set-a'/2,
            '#info-a'/1]).

   '#info-'(Info, Rec) when is_record(Rec, a) ->
       '#info-a'(Info).

   '#get-'(Attrs, Rec) when is_record(Rec, a) ->
       '#get-a'(Attrs, Rec).

   '#set-'(Attrs, Rec) when is_record(Rec, a) ->
       '#set-a'(Attrs, Rec).

   '#new-a'() -> #a{}.
   '#new-a'(Vals) -> '#set-a'(Vals, #a{}).

   '#get-a'(Attrs, R) when is_list(Attrs) ->
       ['#get-a'(A, R) || A <- Attrs];
   '#get-a'(a, R) -> R#a.a;
   '#get-a'(b, R) -> R#a.b;
   '#get-a'(c, R) -> R#a.c.

   '#set-a'(Vals, Rec) ->
       F = fun ([], R, _F1) -> R;
               ([{a, V} | T], R, F1) -> F1(T, R#a{a = V}, F1);
               ([{b, V} | T], R, F1) -> F1(T, R#a{b = V}, F1);
               ([{c, V} | T], R, F1) -> F1(T, R#a{c = V}, F1)
           end,
       F(Vals, Rec, F).

   '#info-a'(size) -> record_info(size, a);
   '#info-a'(fields) -> record_info(fields, a).
   

The generated accessor functions are:

'#new-R'() -> #R{} Instantiates a new record of type R.
'#new-R'(Data) -> #R{} Exactly equivalent to calling '#set-R'(Data,'#new-R'())
'#info-R'(Info) ->
  [FldName]
Info :: fields | size
Equivalent to record_info(fields, R) for the given record type R.
'#info-'(Info, Rec) ->
  [FldName]
Detects the record type of Rec, and calls the corresponding '#info-R'/1 function.
'#get-R'(A, Rec) ->
  Value | [Value]
Returns the value (if A is an atom) of the given field, in Rec (which must be a record of type R), or a list of values (if A is a list of atoms).
'#get-'(A, Rec) ->
  Value | [Value]
Detects the record type of Rec and calls the corresponding '#get-R'(A, Rec) function.
'#set-R'(Data, Rec) ->
  Data | [{Attr::atom(), Value}]
Takes a list of {Attr,Value} tuples and sets the corresponding attributes in the record Rec (which must be of type R). Each Attr in the list must correspond to an actual attribute in the record R.
'#set-'(Data, Rec) ->
  Value | [Value]
Detects the record type of Rec and calls the corresponding '#set-R'(Data, Rec) function.

Function Index

context/2
format_error/1
parse_transform/2
transform/3

Function Details

context/2

context(X1, Context) -> any()

format_error/1

format_error(X1) -> any()

parse_transform/2

parse_transform(Forms, Options) -> any()

transform/3

transform(Forms, F, Acc) -> any()


Generated by EDoc, Sep 21 2011, 20:45:35.