"If the only tool you have is a hammer, you tend to see every problem as a nail."
Abraham Maslov

Thursday, October 23, 2008

Erlang tips and tricks: records

The most awkward thing I ran into while programming in Erlang are things called records. I call them "things" since they are neither Erlang primitives nor data structures. In fact, records are not even understood by Erlang VM itslef (try to define a record in interactive shell). They are some kind of macros (they remind me the ones used in ANSI C) that are translated by the compiler into Erlang native data structures.The biggest problem with records is that you cannot dynamically modify them. For example, suppose you want to create a table in Mnesia, but you don't know at the moment how many columns your table will have. With records, you have to provide all record declarations for all tables you plan to generate on compilation time, which sometimes is simply impossible.I did some research on the topic while writing Mnapi, and I must say it wasn't that easy if you don't know where to start. Finally, I managed to decipher Erlang records secrets mostly by analyzing Mnesia source code. One more reason for using open source software, by the way :-)It turns out that records are in fact wrappers for tuples. So a record defined as:

-record(book, {isbn, author, title}).

gets translated internally into:

{book, isbn, author, title}.

Thus, an equivalent of:

mnesia:write(#book{isbn = I, author = A, title = T}).

is:

mnesia:write({book, I, A, T}).

The only advantage of such crippled structure is that the compiler knows the positions of all elements in the record, so it can always put them in a valid tuple in correct order and find possible errors instantly at the compilation stage. No matter if you write: