Before I start, I have already checked out Handle badarg in Erlang But I am still not successful in my undefined checks so I removed them.
I am building a dummy bank process and when a client does a balance query check to the bank process, the program exits, saying:
Error in process <0.373.0> with exit value:
{badarg,[{project4,client,3,
[{file,"/Users/owner/Desktop/bank.erl"},
{line,27}]}]}
=ERROR REPORT==== 26-Oct-2016::13:34:57 ===
Error in process <0.379.0> with exit value:
{badarg,[{project4,client,3,
[{file,"/Users/owner/Desktop/bank.erl"},
{line,27}]}]}
=ERROR REPORT==== 26-Oct-2016::13:34:57 ===
Error in process <0.375.0> with exit value:
{badarg,[{project4,client,3,
[{file,"/Users/owner/Desktop/bank.erl"},
{line,27}]}]}
=ERROR REPORT==== 26-Oct-2016::13:34:58 ===
Error in process <0.377.0> with exit value:
{badarg,[{project4,client,3,
[{file,"/Users/owner/Desktop/bank.erl"},
{line,27}]}]}
<0.378.0> Balance request: 54>
=ERROR REPORT==== 26-Oct-2016::13:34:58 ===
Error in process <0.378.0> with exit value:
{badarg,[{project4,client,3,
[{file,"/Users/owner/Desktop/bank.erl"},
{line,39}]}]}
<0.372.0> Balance request: 54>
=ERROR REPORT==== 26-Oct-2016::13:34:58 ===
Error in process <0.372.0> with exit value:
{badarg,[{project4,client,3,
[{file,"/Users/owner/Desktop/bank.erl"},
{line,39}]}]}
The code for the simulation is here:
-module(bankSim).
-export([start/0, negativeOrPositive/0, sleep/1, generate_rand_int_list/3, generate_rand/2, client/3, clientSpawn/2, bank/2]).
negativeOrPositive() ->
M = rand:uniform(),
if
M =< 0.5 ->
1;
true ->
-1
end.
sleep(T) ->
receive
after T -> ok
end.
generate_rand_int_list(N,StartVal,Lim) ->
lists:map(fun (_) -> (rand:uniform(Lim-StartVal) + StartVal)* negativeOrPositive() end, lists:seq(1,N)).
generate_rand(StartVal, Lim) ->
rand:uniform(Lim-StartVal) + StartVal.
client([], _ , BankID) ->
BankID ! {goodbye};
client([H|T], Count, BankID) ->
BankID ! {transaction, self(), H},
receive
{Amount, Balance, Success} ->
io:format("Client: ~w, Amount requested: ~w, Bank Balance: ~w, Transaction successful ~w ~n",[self(), Amount, Balance, Success]);
{ X } ->
io:format("The balance is ~w ~n", [X])
end,
sleep(generate_rand(500, 1500)),
Mod = Count rem 5,
if
Mod == 0 ->
io:format("~w Balance request: ",[ self() ]),
BankID! {balance, self()};
true ->
ok
end,
client(T, Count + 1, BankID).
clientSpawn(0, _) ->
io:format("Finished spawning clients ~n",[]);
clientSpawn(N, BankID) ->
spawn(bankSim, client, [ generate_rand_int_list( generate_rand(10, 20), 0, 100) , 1, BankID] ),
clientSpawn(N-1, BankID).
bank(Balance, 0) ->
io:format("Banking simulation ended with a final balance of ~w ~n", [Balance]),
io:format("simulation completed ~n", []);
bank(Balance, NumClients) ->
receive
{balance, Client} ->
Client ! {Balance};
{transaction, Client, Amount} ->
NewBalance = Balance + Amount,
if
NewBalance =< 0 ->
Client ! {Amount, NewBalance, no},
bank(Balance, NumClients);
NewBalance > 0 ->
Client ! {Amount, NewBalance, yes},
bank(NewBalance, NumClients);
true ->
io:format("This will never be printed")
end;
goodbye ->
NewNumClients = NumClients - 1,
bank(Balance, NewNumClients)
end.
start()->
N = generate_rand(2,10),
register(bank ,spawn(bankSim, bank, [generate_rand(2000,3000), N])),
clientSpawn(N,bank).
Any help would be appreciated.
The Erlang documentation will tell you that badarg
means "The argument is of wrong data type, or is otherwise badly formed." Which I never find very elucidating.
Dogbert points out that you missed a recursive call to bank/2
in one of your cases. This is the source of your badarg
s -- but why?
I always think of badarg
as meaning "bad argument sent to a BIF". If you're calling a regular Erlang function, you'll get a function_clause
error, meaning that there was no function clause that matched your data.
The error message you're getting lists two different line numbers. One is for the line
BankID ! {transaction, self(), H},
and the other for
BankID! {balance, self()};
The argument that is bad is BankID
. The reason that it's bad is because it is an atom, bank
. In your start/0
function, you spawn a new bank process and then register the PID of that process as bank
. Then in your client, you're sending messages to the bank
atom and having Erlang resolve that to the registered PID.
It works for a while, but when you hit the missing-recusion case your bank
process terminates. Now there's nobody registered behind the bank
atom, and the send operator blows up because it can't send to a defunct name.
If you changed you code to
Bank = spawn(bankSim, bank, [generate_rand(2000,3000), N]),
clientSpawn(N, Bank).
then you would not get the badarg
, because it's not an error to send messages to a PID where nobody's running. You might enjoy trying that without fixing the bank
loop and seeing what happens.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With