Is there an equivalent expression for the increment/decrement operator e.g. counter++?
I also wonder how to properly do this?
-module(whileloop).
-export([call/0, while_loop/2]).
call() ->
while_loop(10,0).
while_loop(Var,Counter) ->
case Var =:= Counter of
false ->
Counter += 1,
whileloop(Var);
end.
edit:
-module(whileloop).
-export([call/0, while_loop/2]).
call() ->
while_loop(10,0).
while_loop(Var, Counter) ->
case Var =:= Counter of
false ->
while_loop(Var,Counter + 1)
end.
The meaning of C += 1 is to modify the value of C. It is a non sense in Erlang since it can only give the following result:
1> C = C+1.
* 1: variable 'C' is unbound
C = 1.
1
3> C = C+1.
** exception error: no match of right hand side value 2
Keep in mind that "A = B" does not mean assigns the value of B to A, but "pattern match" A against B,
if A is unbound then it will bind to A the value of B;
if A =:= B nothing is done, the process continue;
if A =/= B then the process crashes.
So yes, if you want to have a counter, or any information that change, you must use a state variable which is passed as argument of a recursive loop. From this point of view, your last code is correct, but lets follow what happens when you call "call()" in the shell.
first it calls, in the same process - the shell - the function while_loop(10,0).
10 is not equal to 0 so it calls immediately while_loop(10,1).
10 is not equal to 1 so it calls immediately while_loop(10,2).
and so on until it calls while_loop(10,10). Now 10 =:= 10 is true, and this result does not match any clause of the case, so you get an error and the process crash.
As your code does not contain any message receive and simply loop an loop until it crashes, thhe wole process takes only a few micro seconds, so it looks like it fails immediately.
Depending on what you expect, you can imagine several types of counter, here are 2 examples:
-module(counter).
-compile(export_all).
% one counter that help you to count some events
% interface
start_c1(End) when is_integer(End) ->
spawn(?MODULE,counter1,[End]).
start_link_c1(End) when is_integer(End) ->
spawn_link(?MODULE,counter1,[End]).
inc_c1(Pid) when is_pid(Pid) ->
Ref = make_ref(),
Pid ! {inc,self(),Ref},
receive
{Ref,done} -> done;
{Ref,V} -> V
after 1000 ->
{error,no_response}
end.
value_c1(Pid) when is_pid(Pid) ->
Ref = make_ref(),
Pid ! {get_value,self(),Ref},
receive
{Ref,V} -> V
after 1000 ->
{error,no_response}
end.
stop_c1(Pid) when is_pid(Pid) ->
Pid ! stop.
% the counter
counter1(End) -> counter1_loop(End,0).
counter1_loop(End,V) ->
receive
{inc,Pid,Ref} when V =/= done ->
NewV = case V+1 of
End -> done;
Nv -> Nv
end,
Pid ! {Ref,NewV},
counter1_loop(End,NewV);
{inc,Pid,Ref} ->
Pid ! {Ref,done},
counter1_loop(End,done);
{get_value,Pid,Ref} ->
Pid ! {Ref,V},
counter1_loop(End,V);
stop ->
ok
end.
% One kind of timeout that execute something after a while -
% note it exists a similar one in the library
start_after(T,M,F,A) when is_integer(T), is_list(A) ->
Ref = make_ref(),
{Ref,spawn(?MODULE,after_receive,[T,M,F,A,self(),Ref])}.
cancel_after(P) when is_pid(P) ->
P ! cancel.
% the counter
after_receive(T,M,F,A,Pid,Ref) ->
receive
{cancel,Ref} -> Pid ! {after_receive,Ref,cancelled}
after T ->
Pid ! {after_receive,Ref,done},
apply(M,F,A)
end.
and here how to use them:
1> c("../src/counter").
{ok,counter}
2> {Ref,P} = counter:start_after(5000,io,format,["This is the end!" ]).
{#Ref<0.0.0.29>,<0.33.0>}
This is the end!3>
3> {Refa,Pa} = counter:start_after(50000,io,format,["This is the end!" ]).
{#Ref<0.0.0.34>,<0.35.0>}
4> Pa ! {cancel,Refa}.
{cancel,#Ref<0.0.0.34>}
5> flush().
Shell got {after_receive,#Ref<0.0.0.29>,done}
Shell got {after_receive,#Ref<0.0.0.34>,cancelled}
ok
6> P1 = counter:start_c1(5).
<0.52.0>
7> counter:inc_c1(P1).
1
8> counter:inc_c1(P).
{error,no_response}
9> counter:inc_c1(P1).
2
10> counter:inc_c1(P1).
3
11> counter:value_c1(P1).
3
12> counter:inc_c1(P1).
4
13> counter:inc_c1(P1).
done
14> counter:value_c1(P1).
done
15> counter:inc_c1(P1).
done
16> counter:stop_c1(P1).
stop
17> counter:inc_c1(P1).
{error,no_response}
18>
Just recursively call while_loop with the Counter argument incremented by one:
while_loop(Var, Counter + 1)
Your edited version doesn't have a clause when Var =:= Counter and thus crashes. And you'd better use pattern matching in function clauses.
-module(whileloop).
-export([call/0, while_loop/2]).
call() ->
while_loop(10,0).
while_loop(Var, Var) ->
ok;
while_loop(Var, Counter) ->
while_loop(Var, Counter + 1).
And of course you'd need to do something inside the loop. You can use lambdas for that:
-module(whileloop).
-export([call/0, while_loop/3]).
call() ->
while_loop(10, 0, fun(Counter) -> io:format("Counter: ~p~n", [Counter]) end).
while_loop(Var, Var, _) ->
ok;
while_loop(Var, Counter, Fun) ->
Fun(Counter),
while_loop(Var, Counter + 1, Fun).
Related
The following source doesn't compile because Stopover is unbound.
I'm new to Erlang, how can I rewrite it?
-module(distances).
-export([ path/2 ]).
path( madrid, paris ) ->
{ km, 1049 };
path( paris, moscou ) ->
{ km, 2482 };
path( moscou, berlin ) ->
{ km, 1603 };
path( From, To ) ->
path( From, Stopover ) + path( Stopover, To ).
The usage of this module maybe:
path( madrid, moscou ).
And the epected answer should be { km, 3531}.
The following source doesn't compile because Stopover is unbound.
I'm new to Erlang, how can I rewrite it?
Look at this code:
-module(a).
-compile(export_all).
do_stuff() ->
Stopover.
Here's what happens when I try to compile it:
a.erl:5: variable 'Stopover' is unbound
The variable Stopover was never assigned a value, so erlang has no idea what should be returned by the function do_stuff(). You are doing something similar here:
path( From, Stopover ) + path( Stopover, To ).
The variables From and To are parameter variables for the function path(), and when path() is called, e.g. path(madrid, moscow), then madrid will be assigned to the variable From, and moscow will be assigned to the variable To. Note, however, that nowhere do you assign any value to the variable Stopover.
You need to redefine path() to look like this:
path(From, To, Stopover) ->
Next, you should try to see if adding tuples actually works:
2> {km, 5} + {km, 3}.
** exception error: an error occurred when evaluating an arithmetic expression
in operator +/2
called as {km,5} + {km,3}
3>
Nope!
What you need to do is use pattern matching to extract the distance, an integer, from each tuple, then add the two integers:
{km, Distance1} = path( From, Stopover ),
... = path(Stopover, To),
{km, Distance1 + Distance2}.
This question is already answered by #7stud, and I was wondering how to implement such a path search in erlang. Here is a possible solution:
-module(distances).
-export([ path/2,getTowns/0,start/1, stop/0 ]).
path(From,To) ->
Paths = getPath(),
path(From,To,maps:get(orderedTuple(From,To), Paths, not_found),Paths).
% distanceServer in charge to keep the liste of known distances
% server interfaces
start(Towns) ->
{ok,List} = file:consult(Towns),
Paths = lists:foldl(fun({A,B,D},Acc) -> maps:put(orderedTuple(A,B), D, Acc) end,#{},List),
start(Paths,distance_server).
stop() ->
distance_server ! stop.
getTowns() ->
K = maps:keys(getPath()),
L = lists:usort(lists:flatten([[A,B] || {A,B} <- K])),
io:format("list of towns :~n~p~n~n",[L]).
getPath() ->
distance_server ! {getPath,self()},
receive
Path -> Path
end.
% server fuctions
start(Paths,Server) ->
Pid = spawn(fun() -> distanceServer(Paths) end),
register(Server, Pid).
distanceServer(Path) ->
receive
stop -> stop;
{getPath,From} ->
From ! Path,
distanceServer(Path)
end.
% Searching path
path(From,To,not_found,Paths) -> % if not in the known list, seach for the shortest path
{KM,P} = searchBestPath({0,[From]},To,maps:keys(Paths),{no_dist,no_path}),
case P of
no_path -> not_found;
_ -> {lists:reverse(P),KM}
end;
path(From,To,KM,_) -> % else give the result. Assumption: the known path contains always the best one.
{[From,To],KM}.
searchBestPath({N,[To|_]}=Path,To,_,{BestD,_}) when N < BestD -> Path; % keep the new path if it is better
searchBestPath({N,_},_,_,{BestD,_}=Best) when N >= BestD -> Best; % cancel search if the path so far is longer or equal to the best found
searchBestPath({D,[H|_]=PathSoFar},To,Remaining,Best) ->
Next = [remove(H,{A,B}) || {A,B} <- Remaining, (A =:= H) orelse (B =:= H)], % list of all possible next steps
case Next of
[] -> Best;
Next -> lists:foldl(
fun(X,Acc) ->
{_,ND} = path(H,X), % will always match
R = Remaining -- [orderedTuple(H,X)], % necessary to avoid possible infinite loop in the first search
searchBestPath({D+ND,[X|PathSoFar]},To,R,Acc) % evaluate path for all possible next steps
end,
Best,Next)
end.
% helpers
orderedTuple(A,B) when B > A -> {A,B};
orderedTuple(A,B) -> {B,A}.
remove(X,{X,B}) -> B;
remove(X,{A,X}) -> A.
it uses an external file to define the "known distances", I have used this one for test:
{paris,lyon,465}.
{lyon,marseille,314}.
{marseille,nice,198}.
{marseille,toulouse,404}.
{toulouse,bordeaux,244}.
{bordeaux,paris,568}.
{bordeaux,nantes,347}.
{nantes,paris,385}.
{paris,lille,225}.
{paris,strasbourg,491}.
{lille,strasbourg,525}.
{lille,bruxelles,120}.
{rennes,brest,244}.
{rennes,paris,351}.
{rennes,nantes,113}.
and the result in the shell:
1> c(distances).
{ok,distances}
2> distances:start("distances.txt").
true
3> distances:getTowns().
list of towns :
[bordeaux,brest,bruxelles,lille,lyon,marseille,nantes,nice,paris,rennes,
strasbourg,toulouse]
ok
4> distances:path(bordeaux,bruxelles).
{[bordeaux,paris,lille,bruxelles],913}
5> distances:path(nice,bruxelles).
{[nice,marseille,lyon,paris,lille,bruxelles],1322}
6> distances:path(moscou,paris).
not_found
7> distances:stop().
stop
8>
next step could be to increase the list of known distances each time a new request is done.
Im working on some erlang functions and im also not allowed to use library functions. I have to define a function that drops every other element from a list, starting with the first element.
I have worked on something similar before but i could use BIFs and now i am struggling.
For example, alternate([1,2,3,four,5,6]) is [2,four,6]. I am not sure how to implement it.
spec drop_word(string()) -> string().
drop_word([]) -> [];
drop_word([O|Op]) -> case wsp(O) of
true -> Op;
false -> drop_word(Op)
end.
alternate(List) ->
alternate(List, _Index=0).
alternate([_|T], Index) when Index rem 2 == 0 -> %even indexes
alternate(T, Index+1);
alternate([H|T], Index) when Index rem 2 == 1 -> %odd indexes
[H | alternate(T, Index+1)];
alternate([], _Index) ->
[].
In the shell:
12> a:alternate([1,2,3,four,5,6]).
[2,four,6]
13> a:alternate([1,2,3,four,5]).
[2,four]
But, that can be simplified to:
alternate(List) ->
evens(List).
evens([_|T]) ->
odds(T);
evens([]) -> [].
odds([H|T]) ->
[H | evens(T)];
odds([]) -> [].
In the shell:
6> a:alternate([1,2,3,four,5,6]).
[2,four,6]
7> a:alternate([1,2,3,four,5]).
[2,four]
Here's an accumulator version:
alternate(List) ->
evens(List, []).
evens([_|T], Acc) ->
odds(T, Acc);
evens([], Acc) ->
lists:reverse(Acc).
odds([H|T], Acc) ->
evens(T, [H|Acc]);
odds([], Acc) ->
lists:reverse(Acc).
In the shell:
20> a:alternate([1,2,3,four,5,6]).
[2,four,6]
21> a:alternate([1,2,3,four,5]).
[2,four]
Note that lists:reverse() is highly optimized, so you would never do List ++ [X] many times, which traverses the whole list every time you add an element to the end of the list. Rather, you should always choose to add an element to the head of a list, then call lists:reverse(). Oh yeah, no library functions...a reverse() function is easy to implement yourself, and although it won't be optimized like the erlang version, it will still be more efficient than doing List ++ [X] multiple times.
You can use two atoms drop and keep two match the alternating clauses of do_alternate. Details below in comments.
-module(so).
-export([alternate/1]).
% The exported function starts the actual function and tells it to match the `drop`
% clause. Kept elements of L will be collected in the third argument.
alternate(L) -> do_alternate(drop, L, []).
% The `drop` clause will call the `keep` clause and pass the tail T and the
% currently collected list Acc. The head H will be dropped.
do_alternate(drop, [_|T], Acc) -> do_alternate(keep, T, Acc);
% The `keep` clause will call the `drop` claues and pass the tail T and the
% currently collected list Acc with the head H prepented to it.
do_alternate(keep, [H|T], Acc) -> do_alternate(drop, T, Acc ++ [H]);
% If the arugment list is empty, return the accumulated list.
do_alternate(_, [], Acc) -> Acc.
Example usage:
> c(so).
{ok,so}
9> so:alternate([1,2,3,4,5,6]).
[2,4,6]
10> so:alternate([1,2,3,4,5,6,seven,eight,nine,ten,eleven]).
[2,4,6,eight,ten]
It seems that you want to drop any elements with position which is even. So you can do it like below:
-module(test).
-compile([export_all,debug_info]).
alternate(L) -> do_alternate(L, 0, length(L)).
do_alternate(_, L, L) -> [];
do_alternate([H|T], N, L) ->
case (N band 1) == 0 of
true -> do_alternate(T, N+1, L);
false -> [H] ++ do_alternate(T, N+1, L)
end.
Result in shell:
1> c(test).
test.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,test}
2> test:alternate([1,2,3,four,5,6]).
[2,four,6]
Moreover, if your List only has integer numbers, so you can use BIF like below:
3> lists:partition(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6]).
{[1,3,5],[2,4,6]}
You could pattern match on the list, taking two elements at a time:
alternate([_Odd, Even | T]) ->
[Even] ++ alternate(T);
alternate([]) ->
[].
The specification doesn't say what happens if the list has an odd number of elements, so this function will just crash with a "function clause" error in that case. You could add a third clause to handle that - presumably dropping the last element would be a sensible thing to do:
alternate([_Last]) ->
[];
I have a simple car process implemented in Erlang:
-module(cars).
-compile(export_all).
-record(state, {count=1}).
make_car() ->
spawn_link(fun() -> car_proc(#state{}) end).
car_proc(S) ->
receive
{idle, X} ->
io:format("idling for ~p second(s)~n", [X]),
timer:sleep(X*1000);
{move, {X,Y}} ->
io:format("move; x=~p, y=~p~n", [X,Y]);
{stop, Reason} ->
X = S#state.count,
io:format("stopped with count ~p because ~p~n", [X+1, Reason])
end,
X = S#state.count,
car_proc(S#state{count=X+1}).
I can make it idle, but if I call idle twice in a row, it breaks:
59> C = cars:make_car().
<0.207.0>
60> C!{idle,1}.
idling for 1 second(s)
{idle,1}
61> C!{idle,1}.
idling for 1 second(s)
{idle,1}
62>
=ERROR REPORT==== 9-Apr-2013::00:00:00 ===
Error in process <0.207.0> with exit value: {{badmatch,2},[{cars,car_proc,1,[{file,"cars.erl"},{line,20}]}]}
** exception error: no match of right hand side value 2
in function cars:car_proc/1 (cars.erl, line 20)
Why?
The error occurs on line 20, which is
X = S#state.count
It occurs because the pattern matching fails. The variable 'X' is already defined in this line and it's value is 1, because it has been determined in receive block:
receive
{idle, X} ->
In Erlang value of variable can be defined only one time. When you send message {idle, 1} first time X becomes 1 and default value of S#state.count is 1. So in that case 'X' matches S#state.count. When you send {idle, 1} second time X is 1 and S#state.count is 2 (i.e. X and S#state.count are not equal). So you get error in pattern matching. You can use another variable to avoid the problem. Change two last lines
X = S#state.count,
car_proc(S#state{count=X+1}).
to
Count = S#state.count,
car_proc(S#state{count=Count+1}).
and be happy!
I am new to Erlang, I need to spawn two process running add function, then add the
two numbers.
assigned value of Process one and two is showing the process id, I need catch the value.
How can I read the return value of add(N) function in my calc function?
-module(myerl).
-export([calc/1,add/1]).
add(N) ->
N + 5.
calc(L)
pone = spawn( fun() -> add(A) end),
ptwo = spawn( fun() -> add(B) end),
Result = Pone + Ptwo,
io:format("result ~p~n", [Result]).
You need to use message passing. You must send a message back to the calling process with the result. The spawn function returns a PID (process identifier) to the newly spawned process, not the result of its execution.
This example should do what you're expecting:
calc(A, B) ->
Self = self(), % The spawned funs need a Pid to send to, use a closure
POne = spawn(fun() -> Self ! {self(), add(A)} end),
PTwo = spawn(fun() -> Self ! {self(), add(B)} end),
wait_for_response(POne, PTwo, 0).
wait_for_response(undefined, undefined, Sum) ->
Sum;
wait_for_response(POne, PTwo, Sum) ->
receive
{POne, V} -> wait_for_response(undefined, PTwo, Sum + V);
{PTwo, V} -> wait_for_response(POne, undefined, Sum + V)
end.
#Soup d'Campbells' explanation is good. I instinctively did something slightly different which, in a toy way, anticipates some bad behavior with the child processes. Also, I allow the input to be a list of numbers, not just 2.
-module(myerl).
-export([calc/1, add/1]).
calc(NumList) when is_list(NumList)->
Parent = self(),
_Pids = [spawn(fun()-> Parent ! add(ANum) end) || ANum <- NumList],
collect(length(NumList), 0);
calc(_) ->
{error, badarg}.
collect(0, Sum) ->
Sum;
collect(Cnt, Sum) ->
receive
N when is_number(N) ->
collect(Cnt-1, Sum + N);
_Bad -> % returned something that isnt a number
collect(Cnt-1, Sum)
after 1000 -> % died or is too slow
collect(Cnt-1, Sum)
end.
add(N) ->
N + 5.
-module(test_now).
-compile(export_all).
start() ->
{_, A, _} = now(),
loop(0, A).
loop(A) ->
{_, B, _} = now(),
if
B == A + 1 -> loop(0, B);
true -> loop(A)
end.
loop(T, B) ->
{_, C, _} = now(),
if
C == B + 1 -> io:write(T);
true -> loop(T+1, B)
end.
Logically this code should run 1+ second. But the result returns rapidly, far less than one second. And if I invoke test_now:start() in the Eshell frequently (up-arrow, enter,up-arrow, enter...), the results are always 999999ok.
From the documentation (now/0):
It is also guaranteed that subsequent calls to this BIF returns
continuously increasing values. Hence, the return value from now()
can be used to generate unique time-stamps, and if it is called in a
tight loop on a fast machine the time of the node can become skewed.
So you can't use now/0 to check the time like in your example. You can try os:timestamp/0 instead:
start() ->
{_, S, MS} = os:timestamp(),
loop(0, {S, MS}).
loop(T, {S, MS}=Start) ->
{_, S2, MS2} = os:timestamp(),
if
S2 == S + 1 andalso MS2 == MS -> io:format("~p~n", [T]);
true -> loop(T + 1, Start)
end.
Example:
1> timer:tc(test_timestamp, start, []).
13600591
{1000047,ok}
But if you just want to get some notification in one second consider to use erlang:send_after/3 or erlang:start_timer/3:
start() ->
erlang:send_after(1000, self(), timeout),
loop(0).
loop(T) ->
receive
timeout -> io:format("~p~n", [T])
after
0 -> loop(T + 1)
end.
Example:
1> timer:tc(test_timer, start, []).
27433087
{1000520,ok}
It's not enough to check that the seconds component of now/0 has increased if you want to wait for 1 second (i.e. C == B +1 in the if), you also have to take the microseconds component into consideration.
In the extreme case now() = {_, X, 999999}, which means that the seconds component will be X+1 in just 1 microsecond.
I have no idea why you would always get 999999 loops with this solution.