Erlang concurrent programming - concurrency

Write an Erlang function named calculator that takes no arguments. The function, when run in a process, should wait to receive a message. If the message is in the form of a tuple of four items: { Pid, Operand, X, Y }, do this:
If Operand is add, send a message to Pid with the result of adding X and Y.
If Operand is subtract, send a message to Pid with the result of subtracting Y from X.
If Operand is multiply, send a message to Pid with the result of multiplying X and Y.
If Operand is divide, send a message to Pid with the result of dividing X by Y.
Then, rerun the function.
If the message is in the form of a tuple with two items: { Pid, terminate }, then send a message to Pid of done. Do not rerun the function.
If the message is of any other form, ignore it and rerun the function.
My code:
calculate() ->
receive
{Pid, Operand, X, Y}
if
Operand == "add" -> Pid ! X+Y
Operand == "substract" -> Pid ! Y - X
Operand == "multiply" -> Pid ! X*Y
Operand == "divide" -> Pid ! X/Y
{Pid, terminate} -> Pid ! "done"
_ -> calculate();
end.
Can someone help me with this problem?

Your code does not compile, you should have a look at the basic erlang syntax first.
I give you some clues:
you should not use the if statement for your problem but use pattern matching instead like in
receive
{From,add,X,Y} ->
From ! X+Y,
calculate();
{From,sub,X,Y} ->
...
Generally, for this purpose, use atoms like add rather than string like "add"
you should have a function to start the function calculate/0 in a separate process:
start() ->
spawn(fun() -> calculate() end).

Related

Concurrency in Erlang

The problem I am trying to solve is as follows:
Write an Erlang function named squared that takes no parameters. This function should wait to receive a message. The message will be in the format { Pid, N }, where you may assume that Pid is a process ID and N is a number. The function should send a message to the process ID Pid in the form { Me, X } where Me is the process ID of the process running the function and X is the value of N squared. The function should then end.
so far I have this:
-module(main).
-export([squared/0]).
squared() ->
receive
{Pid,N} -> Pid ! {Me, X}, squared();
terminate -> ok
end.
The error that I am getting is as follows:
3> c(main).
main.erl:7: variable 'Me' is unbound
main.erl:7: variable 'X' is unbound
main.erl:7: Warning: variable 'N' is unused
error
I am also having trouble in the second part of the problem where it is asking us to send a message to the process ID in the form {Me, X}. Where Me is the process ID and X is the value of N squared. How will we do that?
for implement your function you can write a function like bellow
-module(main).
-export([squared/0]).
squared() ->
receive
{Pid,N} ->
Pid ! {self(), N*N},
squared();
terminate ->
ok
end.
Me should be the pid of the receiving process, i.e. self(). N squared is just N*N.
-module(main).
-export([squared/0]).
squared() ->
receive
{Pid, N} ->
Pid ! {self(), N*N};
terminate -> ok
end.
Or, if you want to be more verbous:
squared() ->
Me = self(),
receive
{Pid, N} ->
X = N * N,
Pid ! {Me, X};
terminate -> ok
end.

SML - error in finding elements in list

I'm new to SML. I've written a function which takes 2 int and a list of tuples as input.
fun move(x,y,mylist:(int * int)list): NOxNO =
let
val counter = ref y-1
in
if y=1 then (x,y)
else (
while !counter > 0 do (
if List.exists (fn s => s = (x,!counter)) mylist
then counter := !counter - 1
else break
);
if !counter = 0 then (x,y) else (x,y-1)
)
end
I may have syntax error since I'm a beginner. What the function is trying to do is: it will check the list to find all the tuples whose first element is x and second element varies from 1 to y-1 (tuples like this: (x,1) (x,2) ... (x,y-1) ) and if all of them exist in the list it will return (x,y) else (x,y-1). I used a while loop and a counter. counter is set to y-1 at first and in while loop if (x,counter) was found, counter's value will decrease. At last if counter=0 it means we have found all the tuples. After running the program I encountered this error:
Caught Error ../compiler/TopLevel/interact/evalloop.sml:296.17-296.20
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
What's wrong?
Here's some feedback:
(Error) As Andreas Rossberg said, break doesn't exist. But if you use (), the loop won't terminate when y > 1 and the predicate evaluates to false. You probably want to "break" by setting counter := 0 or counter := -1, depending on what you want the subsequent if !counter = 0 ... to do.
(Error) As Andreas Rossberg said, ref y-1 gives the following type error:
! Toplevel input:
! val r = ref y-1;
! ^
! Type clash: expression of type
! int
! cannot have type
! int ref
This is because function application (ref y) binds tighter than infix operators (y-1). What you mean is ref (y-1), since you can't subtract 1 from a reference.
This isn't very comprehensible or robust. I tried to run it in the simplest case I could think of,
val test1 = move (1,1,[])
But that's a weird base case not handled by the loop. If I change the numbers slightly,
val test2 = move (5,6,[])
then it returns either (5,6) or (5,5) depending on what you change break into.
Based on your description below the code, here is a suggested implementation, although I'm still not completely certain I understand the use of this function:
(* verticalPointsExist (x, y, ps) checks that
* (x,1), (x,2), ..., (x,y-1) are all in ps. *)
fun verticalPointsExist (_, 0, _) = true
| verticalPointsExist (x, y, ps) = List.exists (fn p => (x,y) = p) ps
andalso verticalPointsExist (x, y - 1, ps)
fun move (x, y, ps) =
if verticalPointsExist (x, y, ps) then (x,y) else (x,y-1)
Considerations I made:
Use recursion rather than iteration.
Split the checking part into a helper function, so move doesn't do two things.
Give the functions good names so the code reads more easily. Since I don't know the domain and am really guessing as to whether y is some kind of vertical dimension, there are probably even better names out there. (verticalLineExists? verticalPathClear?) Maybe a more general function will have a better name, e.g. one that took two points and saw that the line is clear between them.
There is no break in ML. You probably just want to write () there. Also, you'll need parens around the argument to ref in line 3.

Interrupt a call in OCaml

I'd like to interrupt a call if it takes too long to compute, like this
try
do_something ()
with Too_long -> something_else ()
Is it possible to do something like that in OCaml? The function do_something may not be modified.
In general the only way to interrupt a function is to use a signal, as Basile suggested. Unfortunately the control flow will be transferred to a signal handler, so that you will be unable to return a value that you like. To get a more fine-grained control, you can run you do_something in separate thread. A first approximation would be the following function:
exception Timeout
let with_timeout timeout f =
let result = ref None in
let finished = Condition.create () in
let guard = Mutex.create () in
let set x =
Mutex.lock guard;
result := Some x;
Mutex.unlock guard in
Mutex.lock guard;
let work () =
let x = f () in
set x;
Condition.signal finished in
let delay () =
Thread.delay timeout;
Condition.signal finished in
let task = Thread.create work () in
let wait = Thread.create delay () in
Condition.wait finished guard;
match !result with
| None ->
Thread.kill task;
raise Timeout
| Some x ->
Thread.kill wait;
x
The solution with threads as well as with signal function has some drawbacks. For example, threads are switched in OCaml in specific iterruption points, in general this is any allocations. So if your code doesn't perform any allocations or external calls, then it may never yield to other thread and will run forever. A good example of such function is let rec f () = f (). In this is your case, then you should run your function in another process instead of thread. There're many libraries for multiprocessing in OCaml, to name a few:
parmap
forkwork
async-parallel
lwt-parallel
There is no built-in facility to perform this precise operation in the standard library, but it is rather straightforward to implement. Using the Thread module, run one thread to perform your main program and a monitoring thread that will kill the program if it lasts too long. Here is a starting implementation:
type 'a state =
| Running
| Finished of 'a
| Failed of exn
| Cancelled of 'a
let bounded_run d f g x =
let state = ref Running in
let p = ref None in
let m = ref None in
let cancel t' = match !t' with
| Some(t) -> Thread.kill t
| None -> ()
in
let program () =
(try state := Finished(f x)
with exn -> state := Failed (exn));
cancel m;
in
let monitor () =
Thread.delay d;
match !state with
| Running -> cancel p; state := Cancelled(g x)
| _ -> ()
in
p := Some(Thread.create program ());
m := Some(Thread.create monitor p);
(match !m with
| None -> ()
| Some(t) -> Thread.join t);
!state
The call bounded_run d f g x runs f x for at most d seconds and returns Finished(f x) if the computation runs in the given time. It might return Failed(exn) if the computation throws an exception. When the computation lasts too long, the returned value is Cancelled(g x).
This implementation has many defaults, for instance, the state and the returned values should have different types (the value Running should not be possible in the returned type), it does not use mutexes to prevent concurrent accesses to the p and m variables holding references to the threads we use. While it is rough at the edges, this should get you started, but for more advanced usage, you should also learn Event or 3rd party libraries such as Lwt or Async – the former will require you to change your function.
(I guess that you are on Linux)
Read more about signal(7)-s. You could use Ocaml's Sys.signal for Sys.sigalarm and Unix module (notably Unix.setitimer)

How do I restart an erlang process in a list?

I have a list construction like this:
[{Value, spawn_link(fun() -> worker(Value, self()) end)} || Value <- List]
So I have a list with values and each value is handed in its own process with the line above. If one worker dies, I want to restart it (with the same value). I have saved the Value in the same tupel as the new process as above. Can I do some list comprehension to determine if the process has died, and in that case, start a new?
Use erlang:monitor/2 to watch for your processes:
List1 = [{Value, spawn_link(fun() -> worker(Value, self()) end)} || Value <- List],
List2 = [{Value, Pid, monitor(process, Pid)} || {Value, Pid} <- List1]
And then wait for messages for monitors, restart your processes if you need and update List2 with new pids and monitors.
To get more info about erlang:monitor/2 read appropriate man page.
In your home made supervisor, don't forget to set process_flag(trap_exit, true) otherwise it will die at the same time one child die, and then all other children too:
1> F = fun() -> timer:sleep(2000) end.
#Fun<erl_eval.20.80484245>
2> F1 = fun() -> timer:sleep(2000), 1/0 end.
#Fun<erl_eval.20.80484245>
3> S = fun() -> spawn_link(F), receive M-> M after 5000 -> no_message end end.
#Fun<erl_eval.20.80484245>
4> S1 = fun() -> spawn_link(F1), receive M-> M after 5000 -> no_message end end.
#Fun<erl_eval.20.80484245>
5> S1b = fun() -> process_flag(trap_exit, true), spawn_link(F1), receive M-> M after 5000 -> no_message end end.
#Fun<erl_eval.20.80484245>
6> self().
<0.40.0>
7> S().
no_message
8> self().
<0.40.0>
9> S1().
=ERROR REPORT==== 15-Mar-2014::06:46:27 ===
Error in process <0.49.0> with exit value: {badarith,[{erlang,'/',[1,0],[]}]}
** exception exit: badarith
in operator '/'/2
called as 1 / 0
10> self().
<0.50.0>
11> S1b().
=ERROR REPORT==== 15-Mar-2014::06:46:39 ===
Error in process <0.53.0> with exit value: {badarith,[{erlang,'/',[1,0],[]}]}
{'EXIT',<0.53.0>,{badarith,[{erlang,'/',[1,0],[]}]}}
12> self().
<0.50.0>
13>
Unless you are doing this for education purpose, I recommend you to use the erlang otp supervisors, with a one_for_one restart strategy.
First, create a function that creates a process that monitors a Pid and executes a Fun when it dies, like so:
on_exit(Pid, Fun) ->
spawn(fun() ->
Ref = monitor(process, Pid),
receive
{'DOWN', Ref, process, Pid, Why} ->
Fun(Why)
end
end).
Now, you can use the on_exit function to create a function for creating processeses that will restart automatically when the process dies:
keep_alive(Fun) ->
process_flag(trap_exit, true),
Pid = spawn_link(Fun),
on_exit(Pid, fun(Why) ->
io:format("Process died: ~p, restarting it~n", [Why]),
keep_alive(Fun) end),
Pid.
With these little two functions, your work to create processes that will restart automatically is reduced to simply calling keep_alive in your list comprehension:
[{Value, keep_alive(fun() -> worker(Value, self()) end)} || Value <- List].
P.S.: These two little functions are presented almost exactly like this in chapter 13 of the book Programming Erlang 2nd Edition, I only did some minor changes to better suit to your case.

If..else if statement within receive..end statement?

I'm trying to create an if..else if condition in Erlang within a receive..end. statement in order to pass two variables A and B so that they can be tested for equivalence.
In the shell I tried typing:
6> Pid = spawn(ifelse,receiving,[]).
** exception error: no match of right hand side value <0.54.0>
7>
What I wanted was to use Pid ! {self(), 1,2}. and Pid ! {self(), 2,2}. to test both cases but something is wrong.
-module(ifelse).
-export([receiving/0]).
receiving() ->
receive
{Pid,A,B}->
if
A =:= B ->
io:format(" B equals A ~n"),
Pid ! "True";
A =/= B ->
io:format(" B does not equal A ~n"),
Pid ! "False";
true -> {error, wrong_value}
end
end.
By the way if I have receiving(A,B) instead with two variables how would I spawn that similarly to Pid = spawn(ifelse,receiving,[]).? I tried using Pid = spawn(ifelse,receiving(1,2),[]). but that gave an error.
As #rvirding commented, Erlang is single assignement. Your problem is probably related to the fact that you have already bound a value to variable Pid and therefore you can't bind any new value to it.
Only in a shell (not recommended in real code) can you unbind a single variable using f(Variable):
1> A = 4.
4
2> f(A).
ok
3> A = 5.
5
or unbind all the variables using f()
Notice that this is only for testing purposes.
As far as I can see your code is right, even though I suggest you to use case and pattern matching instead of an if statement.
So I would rewrite your code as follows:
-module(ifelse).
-export([receiving/0]).
receiving() ->
receive
{Pid, A, B} ->
case A =:= B of
true ->
Pid ! "True";
false ->
Pid ! "False"
end
end.
You can test it as follows:
1> Pid = spawn(ifelse,receiving,[]).
<0.34.0>
2> ShellPid = self().
<0.32.0>
3> Pid ! {ShellPid, 4, 5}.
{0.32.0, 4, 5}
4> flush().
Shell got "False"
Another thing is that I don't see why you should use a string value for "True" and "False" since you could actually use atoms. Moreover your code can work only once because after the if-else or case the process just dies. You can tackle this issue by using a recursive function.
Here is a module with both the modifications:
-module(ifelse).
-export([receiving/0]).
receiving() ->
receive
{Pid, A, B} ->
Pid ! A =:= B
end,
receiving().
and here is how to test it (in a new shell so you don't have to use f() ):
1> Pid = spawn(ifelse,receiving,[]).
<0.34.0>
2> ShellPid = self().
<0.32.0>
3> Pid ! {ShellPid, 4, 5}.
{0.32.0, 4, 5}
4> flush().
Shell got false
5> Pid ! {ShellPid, 4, 4}.
{0.32.0, 4, 4}
6> flush().
Shell got true
If you have define a function receiving/2 in your file, that means you have something like :
-module(ifelse).
-export([receiving/0,receiving/2]).
receiving() ->
some_code.
receiving(A,B) ->
other_code.
you may call it with
Pid = spawn(ifelse,receiving,[1,2]).
By the way, it is not usual to write if statements in erlang, The reason is that if one case doesn't match any condition, the code will crash.
5> F=fun(X) -> if (X rem 2) == 0 -> X+1 end end.
#Fun<erl_eval.6.82930912>
6> F(4).
5
7> F(5).
** exception error: no true branch found when evaluating an if expression
8>
If you want to avoid this, you have to have a default guard (and then it looks like a case).
8> F1=fun(X) -> if (X rem 2) == 0 -> X+1;
8> true -> X end end.
#Fun<erl_eval.6.82930912>
9> F1(4).
5
10> F1(5).
11>
The usual way to code your function is more like this:
receiving() ->
receive
{Pid,_A,_A} when is_pid(Pid) ->
% use the pattern matching to verify that the 2 elements are equal
% and a guard test to check that the first element is a pid.
% Note that in this case it is a strict equals. I use _A because the code doesn't
% care of the value itself
io:format(" B equals A ~n"),
Pid ! "True";
{Pid,_,_} when is_pid(Pid) ->
% use pattern maching to verify the that message is a tupple of 3 elements
% and a guard test to check that the first element is a pid.
% For the 2 last elements I use _, so the data is not bound to any variable,
% only the structure is tested
io:format(" B does not equal A ~n"),
Pid ! "False";
_ -> {error, wrong_value}
end.
I tested this in the shell:
14> F = fun() ->
14> receive
14> {Pid,_A,_A} when is_pid(Pid) ->
14> io:format(" B equals A ~n"),
14> Pid ! "True";
14> {Pid,_,_} when is_pid(Pid) ->
14> io:format(" B does not equal A ~n"),
14> Pid ! "False";
14> _ -> {error, wrong_value}
14> end
14> end.
#Fun<erl_eval.20.82930912>
15> Pid = spawn(F).
<0.58.0>
16> Pid ! {self(),1,2}.
B does not equal A
{<0.51.0>,1,2}
17> % the returm value of "proc ! Mess" is Mess. It is what we get on the console on previous line
17> flush(). % use flush() to get the messages received by the shell
Shell got "False"
ok
18> Pid ! {self(),test,test}. % the process Pid is terminated now. when we send a message to it,
18> % it is simply "lost".
{<0.51.0>,test,test}
19> % it is necessary though to use a new variable Pid1 and spawn a new process
19> % (see rvirding message and user601836 answer)
19> Pid1 = spawn(F).
<0.63.0>
20> Pid1 ! {self(),test,test}.
B equals A
{<0.51.0>,test,test}
21> flush().
Shell got "True"
ok
22> Pid2 = spawn(F).
<0.68.0>
23> Pid2 ! {hello,test,test}.
{hello,test,test}
24> flush().
ok
25> % of course there is no message sent back, no io:format to print something on the console,
25> % the returned value of the function in the error case is "lost".
25> % if you want to have a permanent process you must have a recursive loop,
25> % calling receiving() were needed.