Erlang/OTP Forums

Author Message

<  Advanced Erlang/OTP  ~  Processing records extracted from Mnesia problem

brett hallett
Posted: Wed Sep 19, 2007 5:15 am Reply with quote
User Joined: 21 Aug 2007 Posts: 21
Playing with Joe Armstrong's 'Bank' example, I am trying to develop a function the returns all the account records
so I can print a report.

When I execute the folowing :

========== function in bank.erl ===========================
accounts() -> %% returns :{atomic,{atomic,[[{account,"joe",0}],
%% [{account,"richard",19800}],
%% [{account,"brett",4000}]]}}

fun() ->
M = fun() ->
[mnesia:dirty_read(account, Key) || Key <- mnesia:dirty_all_keys(account)]
end,
mnesia:transaction(M)
end.
===================================

4> bank_client:accounts().
{atomic,{atomic,[[{account,"joe",0}],
[{account,"richard",19800}],
[{account,"brett",4000}]]}}

===================================
Which is correct, Smile , but how do I process the returned result ??

If I set up K ( in the erl shell) , thus :

K = {atomic,{atomic,[[{account,"joe",0}],[{account,"richard",19800}],[{account,"brett",4000}]]}}.

it takes two tuple element extractions to 'get to' the List of accounts for printing purposes,
this seems a bit clumsy !

==================================
eg:

Eshell V5.5 (abort with ^G)
1> K = {atomic,{atomic,[[{account,"joe",0}],[{account,"richard",19800}],[{account,"brett",4000}]]}}.
{atomic,{atomic,[[{account,"joe",0}],
[{account,"richard",19800}],
[{account,"brett",4000}]]}}
2> K1 = element(2,K).
{atomic,[[{account,"joe",0}],
[{account,"richard",19800}],
[{account,"brett",4000}]]}
3> K2 = element(2,K1).
[[{account,"joe",0}],[{account,"richard",19800}],[{account,"brett",4000}]]


What is the appropriate technique to use ???

Thanks.
View user's profile Send private message
Mazen
Posted: Wed Sep 19, 2007 8:17 am Reply with quote
User Joined: 20 Jul 2006 Posts: 164 Location: London
I would suggest patternmatching...

If you know that the value will look like this:
Code:

{A,{B,Value}}

then you would use the following to get the Value:
Code:

{_,{_,Val}} = function_that_returns_that_structure();


If you wan return different structures, use a case clause and patternmatch directly on that. Eg.

Code:

case function_that_returns_different_structures() of
     {_,{_,V}} -> V;
     {_, V}    -> V
end.



On a side note: Are you sure you are getting a list of {atomic, {atomic, ...}} ? Because you are using dirty_reads and you shouldn't get {atomic, _} on a dirty read. Second, if you are using dirty read, why doing so in a transaction? It defeats the purpose doesn't it?

GL,

/Mazen
View user's profile Send private message
brett hallett
Posted: Wed Sep 19, 2007 10:11 pm Reply with quote
User Joined: 21 Aug 2007 Posts: 21
Thanks for your reply,

1) yes I do get the data returned in the format show,
I had tried a number of variations of what you suggest -- without success !
2) I did not know that ditry_reads could operate
'outside' the mnesia:transaction framework. Thanks fror that very useful info.

I'm still feeling my way with Erlang , a very interesting language indeed.
View user's profile Send private message
brett hallett
Posted: Sat Sep 22, 2007 4:51 am Reply with quote
User Joined: 21 Aug 2007 Posts: 21
Following mazen's information I changed my dirty_reads as per accounts() below, and then started expirementing
with possible printing options -- now some confusion beging !.

======================================
accounts() -> %% returns :{atomic,{atomic,[[{account,"joe",0}],
%% [{account,"richard",19800}],
%% [{account,"brett",4000}]]}}
M2 = [mnesia:dirty_read(account, Key)
|| Key <- mnesia:dirty_all_keys(account)],
print(M2),
print2(M2).

%%% ============
print( [L1 | L ]) -> %% {account,"joe",0}
io:fwrite("print1:",[]),
io:fwrite('~p ~n', L1),
print(L);
print([]) ->
io:fwrite("** end accounts list 1 ***~n", []),
ok.
%%% ============
print2( [L1 | L ]) ->
io:fwrite("print2:",[]),
io:fwrite('~p ~n', L1),
print2(L);
print2([]) ->
io:fwrite("** end accounts list 2 ***~n", []),
ok.
=======================================

shell output is:


c(bank).
{ok,bank}
53> bank_client:accounts().
print1:{account,"joe",0}
print1:{account,"richard",19800}
print1:{account,"brett",4000}
** end accounts list 1 ***
print2:{account,"joe",0}
print2:{account,"richard",19800}
print2:{account,"brett",4000}
** end accounts list 2 ***
{aborted,{badarg,ok,[],infinity,mnesia}}

print & print2 output is the same, as expected, however when I change print2 thus :

%%% ============
print2( [L1 | L ]) ->
io:fwrite("print2:",[]),
{A,B,C} = L1, %%%% new
io:fwrite('~p ~n', L1),
io:fwrite("Account : ~s Name: ~s Balance: ~s ~n", [A, B, C]), %%%% new
print2(L);
print2([]) ->
io:fwrite("** end accounts list 2 ***~n", []),
ok.
===============================
the fwrite(s) just stuff up and abort !
I've tried MANY different formats ( ~p, ~s, ~w etc ) without sucess, but the most annoying thing
is that a previously working fwrite

io:fwrite('~p ~n', L1),

does not work now ???
I should get

print2:{account,"joe",0}

, but only 'print2:' appears.

I assume the 'badmatch' below is something to do with my format statement, but I'm
not really sure about that at all !!!

===============================
c(bank).
{ok,bank}
55> bank_client:accounts().
print1:{account,"joe",0}
print1:{account,"richard",19800}
print1:{account,"brett",4000}
** end accounts list 1 ***
print2:
=ERROR REPORT==== 22-Sep-2007::14:23:40 ===
Error in process <0.429.0> with exit value: {{badmatch,[{account,"joe",0}]},[{bank,print2,1},{bank_server,do_call,1},{bank_server,input_handler,1}]}

true

===============================

Any ideas appreciated.
View user's profile Send private message

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum