2017-03-06 5 views
1

これは本当に単純な問題の1つで、私が言語について理解していないものがあると感じました。しかし、私はElixirを学ぼうとしており、私のプログラムは完全に実行されていません。私はここで最小の例を持っています。私は一番下にFoo.go行のコメントを解除し、elixir minimal.exsでそれを実行した場合、私は唯一のspawn &Foo.go/0行のコメントを解除した場合プログラムは早めに終了するようです。

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 

さて、私は0にダウン100からの数字のすべてをある意図した出力を取得します、私は一貫して何の出力も得られません。

しかし、両方の行のコメントを外してプログラムを実行すると、プログラムが終了する前に最初の数(通常は100〜96程度)が100から0になります何らかの理由で。だから私は本当に何が原因でプロセスがランダムな時点で終了するのか分からない。

この混乱が私のために発生した理由は、私がmixを使用して、より大きなプロジェクトをコンパイルしようとしていたことです。プログラムが開始されたように見え、仕事の一部をして終了しました。 mixはちょっとしたことで明らかに動作を停止します。だから私は、エリクシールプログラムを実行するための慣用的な方法がどちらかというと、mixがとにかくしばらくしてそれを終了するように見えることを考えればわかりません。

答えて

3

spawn/1この機能を実行するための新しいプロセスが作成されます。それらは同じではありませんが、Erlang/Elixirプロセスは他のほとんどの言語のスレッドとして考えることができます。

プログラムを起動すると、「メイン」プロセスが何らかの作業を行うようになります。あなたの場合、100から0までの数字を出力するために新しいプロセスを作成します(プロセスAと呼ぶことができます)。しかし、問題はspawn/1がブロックされないということです。 "メイン"プロセスが実行を継続し、 "プロセスA"が戻るのを待つことを意味します。

あなたの「メイン」プロセスは、プログラム全体を終了させる実行を完了しているということが起こります。これは私がこれまで使用してきたすべての言語では正常です。

あるプロセスを別のプロセスで起動し、プログラムを終了する前に実行が終了したことを確認するには、いくつかのオプションがあります。

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 

これを達成するための他の方法がありますができ

task = Task.async(&Foo.go/0) 
Task.await(task) 

。残念ながら、あなたが解決しようとしている問題についてもっと知ることなく、私は基本的な提案しかできません。

これらのことはすべて、mixは実行中のプログラムを任意に停止しないことを示しています。何らかの理由で、「メイン」プロセスは実行を終了していなければなりません。また、mixはビルドツールであり、実際にアプリケーションを実行する方法ではありません(ただし、できます)。繰り返しますが、何をしようとしているのか、コードを見ているのかわからなくても、これ以上のことは何もできません。

+0

ありがとうございました。私の「ミックス」の問題は、エリクシールのプロセスに対する私の誤解と、他の言語がプロセスと呼ぶものとから直接生じていました。 –

+0

もう一つの可能​​な解決策は、 'elixir --ho-halt foo 'でプログラムを実行することです。実行後Erlang VMを停止させることはありません。 Ctrl + Cを2回押してプログラムを終了することができます。 –

関連する問題