2012-02-07 4 views
3

私はErlangのシェルでこれらのコードをテストするとき、それは私にはundefエラーを与えるこれらのコードErlangシェルのすべての関数をエクスポートする必要がありますか?

start() -> 
    spawn(?MODULE, init, [self()]). 

init(From) -> 
    spawn(?MODULE, broadcast, []).  

broadcast() -> 
    Msg = "helloworld", 
    timer:sleep(10000), 
    broadcast(). 

を持って、私は放送関数をエクスポートする必要があり、私はちょうど

+0

書かれているように、 'init/1'関数と' init/1'関数の両方を呼び出せるように 'start/0'関数を両方ともエクスポートする必要があります。あなたが行ったように 'spawn/3'で関数を生成すると、その関数もまたエクスポートされなければなりません。もう一つの方法は、他の人たちが示唆しているように、楽しさを生み出すことです。 – rvirding

答えて

5

コード

spawn(?MODULE, init, [self()]). 

は、あなたが最初の呼び出しがapply(?MODULE,init,[self()])?MODULE:init(self())またはより正確には等しくなるプロセスを生成することを意味します。 ?MODULEはマクロが現在のモジュール名に評価されますが、とにかく外部関数呼び出しなので、?MODULEが使用されていてもこの関数をエクスポートする必要があります。逆

spawn(fun() -> init(self()) end). 

で機能self()の結果とinit/1を呼び出しFUNC fun() -> init(self()) endへの最初の呼び出しで出現しています。それはinit/1をエクスポートすることができないことを意味するローカルコールです。あなたはself()spawn/3のパラメータとして評価された場合spawn(?MODULE, init, [self()])と同様の効果を達成するために

Self = self(), spawn(fun() -> init(Self) end). 

を記述する必要がありのでself()は、新しいプロセス内で実行され、それで別の問題があります。

+0

良い答え:Self = self()、spawn(fun() - > init(Self)end)。 – why

0

が警告でより慎重に見て拒否しています:

test.erl:8: Warning: function init/1 is unused 
test.erl:8: Warning: variable 'From' is unused 
test.erl:11: Warning: function broadcast/0 is unused 
test.erl:12: Warning: variable 'Msg' is unused 

コンパイラはあなたの他の機能は未使用であることを考え、それらをコンパイルすることはありません。代わりにこれを試してみてください:

start() -> 
    spawn(fun() -> init(self()) end). 

init(From) -> 
    spawn(fun() -> broadcast() end). 
+0

"spawn(?MODULE、broadcast、[])"と "spawn(fun() - > broadcast()end)の違いは何ですか? ? – why

1

だけでなく、機能broadcastは、プロセス内で実行されます。したがって、この関数はすべてのプロセスからアクセス可能でなければなりません。同じモジュール内の同じソースコードは、同じモジュールから関数を実行するプロセスを生成しますが、その関数をそのモジュールからエクスポートしてアクセス可能にする必要があります。

これは、spawn(fun() -> broadcast() end).spawn(?MODULE, broadcast, [])の違いに私をもたらします。後者はSpawning with MFAと呼ばれます。この方法では、関数を実行できるように関数をモジュールからエクスポートする必要があります。前者はユニークですが、そのaはfunです。

spawn(fun() -> broadcast() end).この方法を理解するには、これとこの値を比較する必要があります。spawn(fun() -> ?MODULE:broadcast() end).さて、機能broadcastがモジュールにエクスポートされていない場合、ここでは、今2


spawn(fun() -> ?MODULE:broadcast() end).

の後半の話をすることができます: ?MODULE、プロセスがクラッシュします。この場合、関数はこのソースコードが記述されているモジュールの中にあります。
spawn(fun() -> broadcast() end).

この場合、関数はこのソースコードが記述されているモジュールの中になければなりません。しかし、私の考えはこれです。コンパイラはこれを上記のものに変換して、あなたが探している関数がモジュール ?MODULEにあることを、生成されたプロセスに伝えます。

私は実際にコンパイラやランタイムシステムでは教祖ではありませんが、この回答を使用すると思います。私の強いアドバイスは、あなたのソースコードの大部分で、コードまたは関数がこれよりも同じモジュールにあるにもかかわらず、 spawn(fun() -> ?MODULE:broadcast() end).または spawn(fun() -> some_module:broadcast() end).を使用してください: spawn(fun() -> broadcast() end). 。私の個人的な経験から、コードは扱いやすく理解できるようになります。私は生成されたプロセスが指定されたモジュールから関数を見つけて、与えられた引数で実行しなければならないという、この素晴らしい錯覚を得ます。

関連する問題