如何等待用户的输入并继续进行erlang并发编程中的进一步代码?
Posted
技术标签:
【中文标题】如何等待用户的输入并继续进行erlang并发编程中的进一步代码?【英文标题】:How to wait for the input from user and proceed with further code in erlang concurrent programming? 【发布时间】:2019-06-24 23:15:55 【问题描述】:我正在 Erlang 中进行并发编程,我试图在两个用户之间交换消息。因此,我已经硬编码了一组消息,这些消息作为消息从用户 1 一个接一个地发送到另一个用户 2,我正在从键盘读取输入并将该输入作为回复传递给用户 1。但是在执行它时,不接受输入,并且消息传递在没有输入的情况下继续,并在所有进程完成后最后要求输入。
-module(third).
-import(lists,[nth/2]).
-export([start/0,user2/5,user1/3,inp/1]).
inp(P) ->
ok, [S] = io:fread("entry: \n", "~s"),
P ! S.
user2(0, USERID1,_,_,_) ->
USERID1 ! bye,
io:format("finish");
user2(N, USERID1,Mess,Rep,K) ->
USERID1 ! message, self(),Mess,K,
receive
reply ->
S=self(),
spawn(third, inp, [S])
end,
user2(N-1, USERID1,Mess,Rep,K+1).
user1(Mess,Rep,K) ->
receive
bye ->
io:format("conversation over");
message, USERID2,Mess,K ->
io:format("~p~n",[nth(K,Mess)]),
USERID2 ! reply,
user1(Mess,Rep,K+1)
end.
start() ->
Mess=["HEY","sup","how are you","yhank you","bye"],
USERID1=spawn(third, user1, [Mess,Rep,1]),
spawn(third, user2, [5,USERID1,Mess,Rep,1]).
我如何等待输入然后传递该消息。 执行启动模块时输出如下 -
1> c(third).
ok,third
2> third:start().
"HEY"
<0.77.0>
entry:
"sup"
entry:
entry:
"how are you"
entry:
entry:
"yhank you"
entry:
entry:
"bye"
entry:
finishentry:
entry:
conversation overentry:
当它提示输入时,它应该等待输入然后继续。
【问题讨论】:
其实这段代码是行不通的。 start() 函数引用了不存在的 Rep 变量 你可以用任何你想要的方式编写erlang代码,但是如果你需要帮助,那么你必须正确地缩进你的代码。而且,你必须给你的变量和函数起有意义的名字。如您所知,erlang 不是初学者的语言。如果你是编程新手,我建议你改用 python。 【参考方案1】:稍后给出的版本可以按您的预期工作 - 至少我是这么认为的,因为在您的问题和代码中都没有太多评论。
它包含 2 个修改:
-
正如 Odobenus 所说,如果生成函数 inp,函数 user2
立即获得 spawn 的返回值,它是
生成的进程,而不是用户输入的字符串。因此用户2
不等待其他任何事情。该过程仍然存在,因此它将
提示“entry:”,等待输入,但不会使用,
字符串一输入就丢失了。
当您生成函数 user2 时,最后一行还有另一个问题。又是开始
函数在获得新的 pid 后立即停止
过程;由于它是由 shell 命令启动的,因此 shell 采用
立即控制io,user2进程永远得不到
用户输入的字符串,因为它将被 shell 解释为命令。
'''
-module(third).
-export([start/0,user2/4,user1/2,inp/1]).
inp(P) ->
S = io:get_line("entry: \n"),
P ! S.
user2(0, USERID1,_,_) ->
USERID1 ! bye,
io:format("finish");
user2(N, USERID1,Mess,K) ->
USERID1 ! message, self(),Mess,K,
io:format("user2 wait for reply~n"),
receive
reply ->
S=self(),
inp(S)
end,
user2(N-1, USERID1,Mess,K+1).
user1(Mess,K) ->
receive
bye ->
io:format("conversation over");
message, USERID2,Mess,K ->
io:format("~p~n",[lists:nth(K,Mess)]),
USERID2 ! reply,
user1(Mess,K+1)
end.
start() ->
Mess=["HEY","sup","how are you","yhank you","bye"],
USERID1=spawn(third, user1, [Mess,1]),
user2(5,USERID1,Mess,1).
'''
但是,在您的示例中,两个用户进程并没有真正进行通信:它们不检查消息,并且每次都交换完整的消息集合。我建议你检查一下这个其他版本,默认情况下,在 5 次交流后,用户 1 关闭聊天,但用户 2 可以通过输入消息“再见”来停止聊天。
'''
-module(third).
-export([start/0,user2/1,user1/1]).
user2(USERID1) ->
S = io:get_line("entry: \n"),
USERID1 ! message, self(),S,
io:format("user2 wait for reply~n"),
maybe_continue_user2(USERID1,S).
maybe_continue_user2(_,"bye\n") ->
io:format("User2 ends the chat~n");
maybe_continue_user2(USERID1,_) ->
receive
reply,"bye" ->
io:format("bye, close chat~n");
reply,Mess ->
io:format("user2 got ~p~n",[Mess]),
user2(USERID1)
end.
user1([]) ->
io:format("User1 ends the chat~n");
user1([H|T]) ->
receive
message,_,"bye\n" ->
io:format("user 1: conversation over~n");
message, USERID2,Mess ->
io:format("~p~n",[Mess]),
USERID2 ! reply,H,
user1(T)
end.
start() ->
Mess=["HEY","sup","how are you","thank you","bye"],
USERID1=spawn(third, user1, [Mess]),
user2(USERID1).
'''
用户 2 停止聊天的示例:
9> third:start().
entry:
hi
user2 wait for reply
"hi\n"
user2 got "HEY"
entry:
how are you?
user2 wait for reply
"how are you?\n"
user2 got "sup"
entry:
bye
user2 wait for reply
user 1: conversation over
User2 ends the chat
ok
10>
【讨论】:
【参考方案2】:看看这是否有帮助:
-module(my).
-compile(export_all).
start() ->
register(user1, spawn(my, user1, [["Hello!", "How are you?", "Bye"]]) ),
register(user2, spawn(my, user2, []) ),
start_finished.
user1([]) ->
user1, terminated;
user1([String|Strings])->
timer:sleep(500), %% See discussion below.
user2 ! String,
receive
Reply -> io:format("user1 received: ~s~n", [Reply])
end,
user1(Strings).
user2() ->
receive
"Bye" -> io:format("Bye~n");
Msg ->
Prompt = io_lib:format("~s~n>>> ", [Msg]),
Reply = io:get_line(Prompt),
user1 ! Reply,
user2()
end.
在外壳中:
~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
ok,my
2> my:start().
start_finished
Hello!
>>> Hi there!
user1 received: Hi there!
How are you?
>>> Good, and you?
user1 received: Good, and you?
Bye
3>
我不确定我为什么需要timer:sleep()
调用,但它可以防止某些类型的竞争条件导致io:get_line()
发生故障。
【讨论】:
【参考方案3】:从标准输入读取的代码。您在单独的进程中启动它
spawn(third, inp, [S])
每次 user2 进程收到'reply' atom
顺便说一句,用户输入的结果将被发送到 user2 进程并且永远不会使用。
【讨论】:
以上是关于如何等待用户的输入并继续进行erlang并发编程中的进一步代码?的主要内容,如果未能解决你的问题,请参考以下文章