[erlang-questions] Re: Concept of Side-effect

Masklinn masklinn@REDACTED
Fri Sep 18 10:18:55 CEST 2009

On 18 Sep 2009, at 03:35 , Jayson Vantuyl wrote:
>> charge_account(Requestor,UserId,Amount) ->
>>  {atomic,Result} = mnesia:transaction(
>>    fun() ->
>>      [ Current ] = mnesia:read(account,UserId),
>>      OldAmount = Current#account.amount,
>>      New = Current#account{ amount = OldAmount - Amount },
>>      ok = mnesia:write(New),
>>      New
>>    end,
>>    Requestor ! {updated,Result},
>>  ).
> The inner fun() has no side-effects

Not so. The inner fun() executes within a transactional context (that  
of mnesia) and only uses functions relative to that context, which  
means the context manager can handle errors & retries gracefully.

However, mnesia:read and mnesia:write are still side-effecting  
functions, not pure ones: they read and alter external state which  
means the function isn't necessarily repeatable (if you call the fun()  
twice in a row, the record might have been deleted in-between,  
yielding different outcomes).

A pure version of it would be the following:

   fun(Db) ->
     [ Current ] = mnesia:read(Db, account, UserId),
     OldAmmount = Current#account.amount,
     New = Current#account{amount = OldAmount - Amount },
     NewDb = mnesia:write(Db, New),

here, a database is provided as argument to the function and instead  
of mutating that database we create a new one.

This means if we repeatedly call this function and always provide it  
the same Db input, it'll always return the same NewDb. It doesn't rely  
on any external state, managed or not. It's pure.

More information about the erlang-questions mailing list