Records
Currently our world has two parameters: a day counter and a population counter. However while introducing new parameters we would have to write them all every time we want to pass the world into some function. That's not very convenient. Instead of that, we could put all world parameters into an object and address them with a single name. This is where Erlang records come into the scene.
To declare a record you write something like this:
-record(world,
{
day = 0,
population = 100
})
The first argument is record name, the second is a list of record fields, their names and default values. Now let's redesign our event loop so we could pass a record instance instead of a list of arguments:
-module(world).
-export([start/0, loop/1]).
-record(world,
{
day = 0,
population = 100
}).
start() ->
Loop = spawn(world, loop, [#world{}]),
timeline(Loop).
timeline(Loop) ->
receive
after 1000 ->
Loop ! evolve,
timeline(Loop)
end.
loop(World) ->
io:format("Day ~p, Population ~p~n", [World#world.day, World#world.population]),
receive
{Message, Sender} ->
io:format("Message received: ~s~n", [Message]),
loop(World);
evolve ->
loop(update(World))
end.
update(World) ->
World#world
{
day = World#world.day + 1,
population = round(World#world.population * 1.2)
}.
This is how you access a single field of a record by its name:
World#world.day
And this is a partial update of a record. Well, you don't really update an existing record. You create a new one instead:
World#world
{
day = World#world.day + 1,
population = round(World#world.population * 1.2)
}
In the example above we've updated all record fields. However you can update just some of them. The rest of them will keep their values of the record being copied from.