[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),
NewDb
end
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