我觉得这是一个非常简单的问题,其中有一些我对语言不了解的东西。但是我正在努力学习Elixir,而我的程序并没有完全运行。我在这里有一个很小的例子。
defmodule Foo do
def run(0) do
IO.puts("0")
end
def run(n) do
IO.puts(to_string n)
run(n - 1)
end
def go do
run(100)
end
end
# Foo.go
# spawn &Foo.go/0
现在,如果我取消注释底部的Foo.go
行并使用elixir minimal.exs
运行它,那么我得到预期的输出,这是从100到0的所有数字。如果我取消注释只有spawn &Foo.go/0
行,我一直都没有输出。
但是,如果我取消注释两行并运行程序,我会在程序终止之前将数字从100到0(从第一行开始),然后是前几个数字(通常大约100到96左右)原因。所以我真的不知道是什么导致进程在随机点终止。
值得指出的是,这种混乱的原因是我试图使用mix
编译一个更大的项目,当程序似乎开始时,做了一小部分工作,并且然后终止,因为mix
显然在一点之后停止运行。所以我不确定运行Elixir程序的惯用方法是什么,因为mix
似乎在一段时间后终止它。
答案 0 :(得分:3)
spawn/1
将创建一个新进程来运行该函数。虽然它们不一样,但您可以将Erlang / Elixir进程想象成大多数其他语言中的线程。
所以,当你开始你的程序时," main"过程得做一些工作。在您的情况下,它会创建一个新进程(让我们调用它"进程A")将数字从100输出到0.但是,问题是spawn/1
不会阻塞。意思是"主要"过程将继续执行而不是等待过程A"回来。
所以正在发生的事情是你的"主要"进程正在完成执行,结束整个程序。这对我曾经使用的每种语言都是正常的。
如果你想在不同的过程中产生一些工作,并确保它在结束你的程序之前完成执行,你有几个不同的选择。
您可以使用Task
模块。根据这一点,应该有所作为。
task = Task.async(&Foo.go/0)
Task.await(task)
您可以明确send and receive条消息
defmodule Foo do
def run(0, pid) do
IO.puts("0")
# This will send the message back to the "main" thread upon completion.
send pid, {:done, self()}
end
def run(n, pid) do
IO.puts(to_string n)
run(n - 1, pid)
end
# We now pass along the pid of the "main" thread into the go function.
def go(pid) do
run(100, pid)
end
end
# Use spawn/3 instead so we can pass in the "main" process pid.
pid = spawn(Foo, :go, [self()])
# This will block until it receives a message matching this pattern.
receive do
# The ^ is the pin operator. It ensures that we match against the same pid as before.
{:done, ^pid} -> :done
end
还有其他方法可以实现这一目标。不幸的是,如果不了解您要解决的问题,我只能提出基本建议。
尽管如此,mix
不会随意停止正在运行的程序。无论出于何种原因,"主要"进程必须已完成执行。另外mix
是一个构建工具,不是你应该运行应用程序的方式(尽管如此,你可以)。再一次,在不知道你想要做什么或看到你的代码的情况下,我不能给你更多的东西。