RFC: exprecs and record versions

Ulf Wiger <>
Thu Apr 29 11:17:08 CEST 2010


Inspired by a recent discussion on the riak mailing list,
I went back to my exprecs module and started playing with
a very obscure feature supporting conversions between different
versions of records.

http://github.com/uwiger/parse_trans

I implemented it quite some time ago, but never documented
it; the 'playing' was needed in order to remind myself of how
it actually worked.

My question is whether this might be useful as-is (i.e. needing
only some documentation), or whether some vital piece is missing
in order to make it useful. My initial intent was for it to be
used in code_change callbacks, rather than having to explitly
pattern-match on the old instance of a record using its tuple
representation.

Here is an example:

-module(test_exprecs).

-export([f/0]).

-compile({parse_transform, exprecs}).

-record(r, {a, b, c}).
-record(foo, {a}).
-record(foo__v1, {a,b}).
-record(foo__v2, {a,b,c = 17}).

-export_records([r,foo]).


f() ->
     {new, '#new-r'([])}.


To see how the code is transformed, parse_trans:pp_beam(Mod)
can be helpful. Mod is either the module name (if the beam file
is in the CWD), or the full beam file name.

Here's a small shell interaction:

Eshell V5.7.5  (abort with ^G)
1> Foo = test_exprecs:'#new-foo'([{a,17}]).
{foo,17}
2> Foo_v1 = {foo,17,a}.   % no API for creating old versions
{foo,17,a}
3> Foo_v2 = {foo,17,a,b}.
{foo,17,a,b}
4> test_exprecs:'#info-foo'(fields).
[a]
5> test_exprecs:'#info-'(foo,fields,"v1").
[a,b]
6> test_exprecs:'#info-'(foo,fields,"v2").
[a,b,c]
7> test_exprecs:'#convert-'("v2",Foo_v2). 
         {{foo,17},[{b,a},{c,b}]}

The last command (7) converts an old record to the
new format (record name without the __Vsn suffix is
always the newest definition). It returns {Rec,Discarded},
where Discarded are the {AttrName, Value} pairs that were
in the old record, but not in the new. Attributes that are
in the new record but not the old will get default values,
as per the record definition.

Again, the original intent was for code_change/3 functions:

code_change(FromVsn, State, _Extra) ->
   {NewState,[]} = '#convert-'(FromVsn,State),
   {ok, NewState}.

For the above to work, you would need to quote the versioned
records: -record('state__1.5', {...}), because of the dots
in the version string. You could also make sure that the
current record definition also exists with a version suffix.

Given the complete lack of documentation, I would guess that
the opportunity for backwards-incompatible changes is good,
if you feel that the concept needs major surgery. :)

BR,
Ulf W
-- 
Ulf Wiger
CTO, Erlang Solutions Ltd, formerly Erlang Training & Consulting Ltd
http://www.erlang-solutions.com
---------------------------------------------------

---------------------------------------------------

WE'VE CHANGED NAMES!

Since January 1st 2010 Erlang Training and Consulting Ltd. has become ERLANG SOLUTIONS LTD.

www.erlang-solutions.com



More information about the erlang-questions mailing list