Printing 为什么我会收到两次相同的信息?
我是Erlang的新手,我正在开发一个小程序来模拟收集罐头的机器人:Printing 为什么我会收到两次相同的信息?,printing,erlang,otp,gen-server,Printing,Erlang,Otp,Gen Server,我是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(NewB
-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).
当我运行代码时,在某些情况下,我会得到两次打印,但我不会从drop函数中得到最后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@Usuario2>
相信:[{bin_位置,0},
{can_位置,4},
{控股,[]},
{我的位置,4},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,4},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,4},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,4},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,3},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,3},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,3},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,3},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,2},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,2},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,2},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,2},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,1},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,1},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,1},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,1},
{num_cans,1}]
相信:[{bin_位置,0},
{can_position,nil},
{控股,[]},
{我的位置,0},
{num_cans,1}]
这是我的荣幸
我做错什么了吗?它是否与每个流程需要执行的时间有关?我也不知道是否有办法用OTP实现它,我的意思是,使用gen_服务器或其他什么
非常感谢你 尝试运行以下代码:
-module(so1).
-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),
io:format("add clause:~n"),
print(N1),
action(self(),N1),
believes(N1);
{remove, Key}->
N2=maps:remove(Key, NewBelieves),
io:format("remove clause:~n"),
print(N2),
action(self(),N2),
believes(N2);
{update, Key, Value}->
N3=NewBelieves#{Key => Value},
io:format("update clause:~n"),
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->
io:format("action() is calling move()~n"),
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),
io:format("move() is going to send update message~n"),
case Dir of
right-> PID ! {update, my_position, MyPosition+1};
left -> PID ! {update, my_position, MyPosition-1}
end.
hold(PID)->
io:format("hold() is sending add, update messages,~n"),
io:format("which will result in two prints:~n"),
PID ! {add, holding, []},
PID ! {update, can_position, nil}.
drop(PID)->
io:format("drop() is sending remove, update, add messages,~n"),
io:format("which will result in three prints:~n"),
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).
输出将显示您的代码是一团混乱。此外,当您创建多个进程时,输出可以交错并以与写入不同的顺序出现
我对二郎很陌生
您只能编写调试技能所能处理的程序。现在坚持20行或更少。您可能还想尝试使用单步执行代码
我也不知道有没有办法用OTP来实现,
使用gen_服务器或其他东西
任何带有receive子句和保存状态的循环变量的无限循环都可以被视为服务器,因此可以实现为gen_服务器。这里的预期输出是什么?请通过删除不相关的代码创建一个最小的示例,很难理解这段代码到底在做什么。我应该只收到一条信息。我用gen_服务器行为解决了这个问题,一旦你知道如何使用它,它就棒极了!谢谢你的回答:D。