Erlang 从Elixir进程打印到控制台
所以,我开始玩Elixir,我想制作两个模块。提示您输入消息,然后将消息发送给另一个程序,该程序将确认收到消息,这将导致第一个程序打印出消息 嗯,我有很多问题 发送者如下:Erlang 从Elixir进程打印到控制台,erlang,elixir,Erlang,Elixir,所以,我开始玩Elixir,我想制作两个模块。提示您输入消息,然后将消息发送给另一个程序,该程序将确认收到消息,这将导致第一个程序打印出消息 嗯,我有很多问题 发送者如下: defmodule PracticeCaller do def start do spawn(&sloop/0) end def sloop do pid = :erlang.spawn(&PracticeServer.start/0)
defmodule PracticeCaller do
def start do
spawn(&sloop/0)
end
def sloop do
pid = :erlang.spawn(&PracticeServer.start/0)
message = IO.gets "Enter a message:"
send(pid, {self, message})
receive do
{_caller, reply} -> IO.puts "#{reply}"
end
sloop
end
end
接收者在这里:
defmodule PracticeServer do
def start do
spawn(&loop/0)
end
defp loop do
receive do
{caller, "kill"} -> send(caller, {self, "Process Dead"})
Process.exit(self, :kill)
{caller, _} -> send(caller, {self, "Thank you for your message!"})
end
loop
end
end
我的第一个问题是,当我启动发送方循环时,终端会提示我输入消息,但它不会打印收到的消息
其次,当我输入“kill”时,终端冻结,因为我不知道如何处理:kill响应
有没有关于解决这些问题的帮助?第一个问题是:
pid = :erlang.spawn(&PracticeServer.start/0)
事实上,PracticeServer.start/0
再次调用spawn
。这意味着这里的pid
不是指运行PracticeServer.loop/0
的进程,而是指产生PracticeServer.loop/0
并立即退出的进程
如果我改变:
pid = :erlang.spawn(&PracticeServer.start/0)
只是:
pid = PracticeServer.start
有些事情开始起作用:
Enter a message:hello
Thank you for your message!
Enter a message:world
Thank you for your message!
但是:
这是因为IO.gets/1
包含尾随的换行符,这意味着PracticeServer.loop/0
中的{caller,“kill”}
模式从不匹配
可以通过更改以下内容来解决此问题:
message = IO.gets "Enter a message:"
到
现在:
另一个问题是,您当前正在泄漏进程。您不是重用生成的服务器,而是为每条消息生成一个新服务器。另外,处理可被“终止”的递归receive
的惯用方法是在希望进程终止时不执行递归调用。以下是一些重构代码:
defmodule PracticeCaller do
def start do
spawn(fn -> loop(PracticeServer.start) end)
end
def loop(server) do
message = IO.gets("Enter a message: ") |> String.trim_trailing
send(server, {self, message})
receive do
{_caller, reply} ->
IO.puts "#{reply}"
# Only continue if process is not dead.
# Comparing against strings is usually not idiomatic, you may want to
# change that.
if reply != "Process Dead" do
loop(server)
end
end
end
end
defmodule PracticeServer do
def start do
spawn(&loop/0)
end
def loop do
receive do
{caller, "kill"} ->
send(caller, {self, "Process Dead"})
{caller, _} ->
send(caller, {self, "Thank you for your message!"})
loop
end
end
end
PracticeCaller.start
:timer.sleep(:infinity)
请注意,即使在发送“kill”之后,这也不会停止VM。如果这只是一个脚本,那么当消息为“进程死机”时,您可以将:erlang.halt
添加到PracticeCaller.loop/1
,以立即停止VM。第一个问题是:
pid = :erlang.spawn(&PracticeServer.start/0)
事实上,PracticeServer.start/0
再次调用spawn
。这意味着这里的pid
不是指运行PracticeServer.loop/0
的进程,而是指产生PracticeServer.loop/0
并立即退出的进程
如果我改变:
pid = :erlang.spawn(&PracticeServer.start/0)
只是:
pid = PracticeServer.start
有些事情开始起作用:
Enter a message:hello
Thank you for your message!
Enter a message:world
Thank you for your message!
但是:
这是因为IO.gets/1
包含尾随的换行符,这意味着PracticeServer.loop/0
中的{caller,“kill”}
模式从不匹配
可以通过更改以下内容来解决此问题:
message = IO.gets "Enter a message:"
到
现在:
另一个问题是,您当前正在泄漏进程。您不是重用生成的服务器,而是为每条消息生成一个新服务器。另外,处理可被“终止”的递归receive
的惯用方法是在希望进程终止时不执行递归调用。以下是一些重构代码:
defmodule PracticeCaller do
def start do
spawn(fn -> loop(PracticeServer.start) end)
end
def loop(server) do
message = IO.gets("Enter a message: ") |> String.trim_trailing
send(server, {self, message})
receive do
{_caller, reply} ->
IO.puts "#{reply}"
# Only continue if process is not dead.
# Comparing against strings is usually not idiomatic, you may want to
# change that.
if reply != "Process Dead" do
loop(server)
end
end
end
end
defmodule PracticeServer do
def start do
spawn(&loop/0)
end
def loop do
receive do
{caller, "kill"} ->
send(caller, {self, "Process Dead"})
{caller, _} ->
send(caller, {self, "Thank you for your message!"})
loop
end
end
end
PracticeCaller.start
:timer.sleep(:infinity)
请注意,即使在发送“kill”之后,这也不会停止VM。如果这只是一个脚本,您可以在消息为“进程停止”时将
:erlang.halt
添加到PracticeCaller.loop/1
,以立即停止VM。服务器停止后,您希望客户端做什么?我希望客户端也被停止,但是我不知道该怎么做。你希望客户端在服务器死后做什么?我希望客户端也被杀死,但我不知道该怎么做。