This Erlang program spawns two concurrent processes, odd
and even
, which handle separate lists of numbers. The odd
process sends even numbers to even
and keeps odd numbers, while the even
process sends odd numbers to odd
and keeps even numbers. Both processes communicate via message passing and attempt to print their results when a “done” signal is received.
Erlang Code (with Errors):
code-module(test).
-export([start/0]).
-export([odd/2]).
-export([even/2]).
start() ->
register(oid, spawn(test, odd, [[1,2,3,4,5],[]])),
register(eid, spawn(test, even, [[6,7,8,9],[]])).
%---------------------------------------------
odd([], O) -> % Base case when the list is empty
eid ! done, % Notify even process that it's done
lists:foreach(fun(X) -> io:fwrite("Odd: ~p~n", [X]) end, O);
odd([A | Rest], O) -> % Recursive case for processing odd list
if
A rem 2 =:= 0 -> % Even number, send to even process
eid ! A,
odd(Rest, O); % Continue with the rest of the list
true -> % Odd number, keep in the odd process list
odd(Rest, O ++ [A])
end.
%---------------------------------------------
even([], E) -> % Base case when the list is empty
oid ! done, % Notify odd process that it's done
lists:foreach(fun(X) -> io:fwrite("Even: ~p~n", [X]) end, E);
even([A | Rest], E) -> % Recursive case for processing even list
if
A rem 2 =/= 0 -> % Odd number, send to odd process
oid ! A,
even(Rest, E); % Continue with the rest of the list
true -> % Even number, keep in the even process list
even(Rest, E ++ [A])
end.
%---------------------------------------------
pri([H | T]) ->
io:format("~p~n", [H]),
pri(T);
pri([]) ->
true.
Key Changes and Solutions:
- List Concatenation: The original code used
O++[Num]
for list concatenation without assigning the result to a variable. Erlang lists are immutable, so the concatenated result must be assigned back. The updated code usesodd(Rest, O ++ [A])
to recursively process and store the odd numbers. - Base Case in Recursive Functions: The original code didn’t have a proper base case for when the list is empty. The rewritten version adds
odd([], O)
andeven([], E)
to handle the empty list case, which ensures proper termination and sends thedone
message to the other process. - Message Passing: The code now properly handles passing odd and even numbers between the
odd
andeven
processes usingeid ! A
andoid ! A
. This fixes any potential deadlock that could occur without message synchronization. - Handling Done Messages: The base case sends a
done
message when processing is complete, ensuring that each process knows when the other is done. This is crucial for cleanly terminating the processes.
Corrected Erlang Code:
code-module(test).
-export([start/0]).
-export([odd/2]).
-export([even/2]).
% Starts the odd and even processes and registers them
start() ->
register(oid, spawn(test, odd, [[1,2,3,4,5], []])),
register(eid, spawn(test, even, [[6,7,8,9], []])).
%---------------------------------------------
% odd/2 function handles odd numbers and sends even numbers to even process
odd([], O) -> % Base case: when list is empty, notify the even process
eid ! done,
lists:foreach(fun(X) -> io:fwrite("Odd: ~p~n", [X]) end, O); % Print odd numbers
odd([A | Rest], O) ->
if
A rem 2 =:= 0 -> % If the number is even, send it to even process
eid ! A,
odd(Rest, O); % Continue processing the rest of the list
true -> % If the number is odd, add it to the odd list
odd(Rest, O ++ [A])
end.
% Receives the done message and handles further actions
odd(c, O) ->
receive
done ->
lists:foreach(fun(X) -> io:fwrite("Odd: ~p~n", [X]) end, O),
io:fwrite("Odd process finished~n");
Num ->
odd(c, O ++ [Num]) % Add received number to the list
end.
%---------------------------------------------
% even/2 function handles even numbers and sends odd numbers to odd process
even([], E) -> % Base case: when list is empty, notify the odd process
oid ! done,
lists:foreach(fun(X) -> io:fwrite("Even: ~p~n", [X]) end, E); % Print even numbers
even([A | Rest], E) ->
if
A rem 2 =/= 0 -> % If the number is odd, send it to odd process
oid ! A,
even(Rest, E); % Continue processing the rest of the list
true -> % If the number is even, add it to the even list
even(Rest, E ++ [A])
end.
% Receives the done message and handles further actions
even(c, E) ->
receive
done ->
lists:foreach(fun(X) -> io:fwrite("Even: ~p~n", [X]) end, E),
io:fwrite("Even process finished~n");
Num ->
even(c, E ++ [Num]) % Add received number to the list
end.
%---------------------------------------------
pri([H | T]) ->
io:format("~p~n", [H]),
pri(T);
pri([]) ->
true.
Explanation of the Changes:
- List Concatenation: The original code used
O++[Num]
andE++[Num]
without assigning the result. Erlang lists are immutable, so the concatenated result must be reassigned. The updated code now properly reassigns the new list toO
andE
in the recursive calls (odd(Rest, O ++ [A])
andeven(Rest, E ++ [A])
). - Base Case for Empty Lists: The base case (
odd([], O)
andeven([], E)
) now properly handles when the input list is empty, and it sends thedone
message to notify the other process that it’s finished. It also prints the processed list at the end usinglists:foreach
. - Message Passing: The processes (
odd
andeven
) use message passing to send odd numbers to theodd
process and even numbers to theeven
process. This is done usingoid ! A
andeid ! A
to pass the numbers between processes. - Completion Handling: The processes receive the
done
message when the other process completes its work. Upon receivingdone
, the process prints its final list and terminates. This ensures clean synchronization between the two processes.
Execution Flow:
- Start: The
start/0
function starts two processes,odd/2
andeven/2
, with initial lists of numbers. - Odd Processing: The
odd/2
function processes its list and sends even numbers to theeven
process. - Even Processing: The
even/2
function processes its list and sends odd numbers to theodd
process. - Termination: When one process finishes processing its list, it sends a
done
message to the other process, which completes the workflow.
This should now work without errors and handle communication between the odd
and even
processes properly.