[erlang-questions] maps or records?

Siraaj Khandkar <>
Tue Mar 1 03:43:30 CET 2016

On 2/29/16 1:39 PM, Jesper Louis Andersen wrote:
> On Mon, Feb 29, 2016 at 4:28 PM, Siraaj Khandkar <>
> wrote:
>> In other words, I'm saying it is very possible to have this cake (of
>> public structure) and eat it too (in private, without anyone accessing the
>> rapidly-changing, secret cream) :)
> You are so close to the idea of view types, and Torben hinted me I should
> say something about them :)

The basic idea is indeed very similar, but, of course, far less ambitious :)

My main point is that the idea of an API compatibility is a social 
contract to, once published, not remove parts of a signature of a component.

The following two components make equivalent contracts with their users:

     -export([new/0, ..., get_a/1, get_b/1]).
     -record(foo, {a :: a(), b :: b(), c :: super_secret()}).
     -opaque foo() :: #foo{}.
     -spec new() -> foo().
     -spec get_a(foo()) -> a().
     -spec get_b(foo()) -> b().

     -export_type([foo/0, bar/0]).
     -export([new/0, ..., view/1]).
     -record(foo, {a :: a(), b :: b(), c :: super_secret()}).
     -record(bar, {a :: a(), b :: b()}).
     -opaque foo() :: #foo{}.
     -type bar() :: #bar{}.
     -spec new() -> foo().
     -spec view(foo()) -> bar().

Here, for simplicity, bar is just a subset of foo, but, in practice, 
it's fine for them to have nothing in common, of course (so one can do 
more complicated things, if desired).

Which one to choose is pretty much art - all depends on author's other 

> In other words: exporting records across application boundaries tend to
> lock them down, so be pretty sure they are set in stone.

Precisely. Just like any API should be, within bounds of it's promise to 
the users (such as semver).

More information about the erlang-questions mailing list