Я новичок в Erlang, и я разрабатываю небольшую программу для моделирования робота, который собирает банки:
-export([start/0]).
start()->
Believes=#{bin_position=>0, num_cans=>1, can_position=>4, my_position=>1},
PID=spawn(fun()-> believes(Believes) end),
action(PID,Believes).
believes(NewBelieves)->
receive
{add,Key,Value}->
N1=maps:put(Key,Value,NewBelieves),
print(N1),
action(self(),N1),
believes(N1);
{remove, Key}->
N2=maps:remove(Key, NewBelieves),
print(N2),
action(self(),N2),
believes(N2);
{update, Key, Value}->
N3=NewBelieves#{Key => Value},
print(N3),
action(self(),N3),
believes(N3);
{get}->
action(self(),NewBelieves),
believes(NewBelieves)
end.
print(Map)->
List=maps:to_list(Map),
io:format("Believes: ~p~n",[List]).
action(PID, Map)->
case {is_holding(Map),is_over_bin(PID,Map)} of
{false,false}->
%io:format("Is not holding and is not over the bin ~n"),
%timer:sleep(1000),
case is_over_can(PID,Map) of
false->move(PID,right,Map);
% timer:sleep(1000);
_->hold(PID)
%timer:sleep(1000)
end;
{_,false}->
%io:format("Is holding but is not over the bin ~n"),
%timer:sleep(1000),
move(PID, left, Map);
%timer:sleep(1000);
{_,_}->
%io:format("Is holding and is over the bin ~n"),
%timer:sleep(1000),
drop(PID),
timer:sleep(10000),
exit(self(),kill)
end.
is_over_can(PID, Map)->
case same_position(maps:find(my_position,Map),maps:find(can_position, Map)) of
equal->hold(PID);
_->false
end.
is_over_bin(PID, Map)->
case same_position(maps:find(my_position,Map),maps:find(bin_position, Map)) of
equal->drop(PID);
_->false
end.
is_holding(Map)->
maps:is_key(holding,Map).
%is_gripper_on(Map)->
% map:is_key(gripper_on,Map).
%is_touching(Map)->
% map:is_key(touching,Map).
same_position({ok,A},{ok,B}) when A=:=B -> equal;
same_position(_, _) -> not_equal.
move(PID, Dir, Map)->
{ok,MyPosition}=maps:find(my_position,Map),
case Dir of
right->PID ! {update, my_position, MyPosition+1};
left->PID ! {update, my_position, MyPosition-1}
end.
hold(PID)->
PID ! {add, holding, []},
PID ! {update, can_position, nil}.
drop(PID)->
PID ! {remove, holding},
PID ! {update, num_cans, 0},
PID ! {add, cans_collected, 1},
timer:sleep(10000),
io:format("Todas las latas han sido recogidas.~n"),
timer:sleep(10000),
exit(PID,kill).
И когда я запускаю код, в некоторых случаях я получаю отпечаток дважды (и я не получаю последние 3 отпечатка из функции перетаскивания):
пруэба2:старт().
Верит: [{bin_position,0},{can_position,4},{my_position,2},{num_cans,1}]
Верит: [{bin_position,0},{can_position,4},{my_position,3},{num_cans,1}]
{обновление, моя_позиция, 2}
Верит: [{bin_position,0},{can_position,4},{my_position,4},{num_cans,1}]
(Prueba@Usuario)2> Верит: [{bin_position,0}, {can_position,4}, {holding,[]}, {my_position,4}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,4}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,4}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,4}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,3}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,3}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,3}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,3}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,2}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,2}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,2}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,2}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,1}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,1}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,1}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,1}, {num_cans,1}]
Верит: [{bin_position,0}, {can_position,nil}, {holding,[]}, {my_position,0}, {num_cans,1}]
Todas las latas han sido recogidas.
Я делаю что-то неправильно? Связано ли это со временем, которое требуется каждому процессу для его выполнения? Я также не знаю, есть ли способ реализовать это с помощью OTP, я имею в виду, используя gen_server или что-то в этом роде.
Большое спасибо!