2009-08-21 3 views
13

xyzを呼び出す関数の名前で呼びたいと思います。Erlangでは、関数をどのように動的に呼び出すのですか?

-module(sample). 
-export([xyz/1]). 

xyz(Name) -> Name(). 

p() -> "you called p". 
g() -> "you called g". 

しかし、私は次のエラーを取得する:

1> c(sample.erl). 
./sample.erl:6: Warning: function p/0 is unused 
./sample.erl:7: Warning: function g/0 is unused 
{ok,sample} 
2> sample:xyz('p'). 
** exception error: bad function p 
    in function sample:xyz/1 
3> 
+2

私のErlangの知識はゼロに近いですが、私はあなたがしたい場合は、Pをエクスポート(そしておそらくグラムしているとしそれを使用することもできます)。 – balpha

答えて

22

あなたがpとgをエクスポートする必要があることが正しいです。その後、apply/3を使用して呼び出すことができます。

erlang:apply(sample, p, []) 

Fun(...)構文で使用できるのは、値だけです。あなたは原子値を渡しています。エラーメッセージが表示されるため、アトムは「不良関数」です。あなたはその後、先に行く

xyz(p) -> fun p/0; 
xyz(g) -> fun g/0. 

に似た何かをして

Fun = xyz(p), 
Fun() 
+0

ありがとうございます。私は今これを持っています: - モジュール(サンプル)。 -export([xyz/1、p/0、g/0])。 xyz(名前) - >適用(サンプル、名前、[])。 p() - > "pを呼び出しました"。 g() - > "gと呼ばれた" とすることができます: 26> c(sample.erl) {ok、sample} 27>サンプル:xyz( 'p')。 "p: 28> sample:xyz(p)を呼び出しました。 "p: 29> sample:xyz( 'g')と呼んでいます。 "g: 30> sample:xyz(g)と呼んでいます。 "gと呼んだ" しかし、これらの関数をエクスポートしない方法はありませんか?私はそれをモジュールユーザーに見せたくありません。 apply/2のどちらでも動作するようには見えません。もちろん、私は初心者です – ottodidakt

+1

パターンマッチングでコールマッピングをハードコードするか、関数をエクスポートします。 – Zed

+0

未報告の関数を 'リーク'させる唯一の方法は、それを参照する楽しい値を返すことです。 fun値を返す私の明示的なxyz/1関数とまったく同じです。 – Christian

7

パターンマッチを使用するイディオムで呼び出すことができます。

-module(sample). 
-export([xyz/1]). 

xyz(p) -> p(); 
xyz(q) -> g(). 

p() -> "you called p". 
g() -> "you called g". 

あなたが使用することができ、動的になりたい場合はgen_eventサーバー。基本的に

何これがあることはそうのようなキー/機能のペアを構成状態を保持するサーバである:

[{p, #func1}, 
{g, #func2}, 
{..., ...}, 
...] 

あなたは、その後、基本的な機能にイベントをバインドすることができます。 (それよりも、それまでもう少し、と言って、不必要がある。

+1

これは技術的には1つの方法ですが、私はその質問を、動的に関数を呼び出すために言語を機能させるのに役立つと考えています。適用関数は、彼が探している答えです。 –

8
-module(sample). 
-export([xyz/1, p/0, g/0]). 

xyz(Name) -> ?MODULE:Name(). 

p() -> "you called p". 
g() -> "you called g". 


1> sample:xyz(p). 
"you called p" 
+1

これはかなりクールです。 「?MODULE」についてはどこで読むことができますか?今私たちがpとqをエクスポートするだけで済むならば。 – ottodidakt

+0

定義済みのマクロは次のとおりです。http://erlang.org/doc/reference_manual/macros.html#7.3残念ながら、Erlangは「公開」と「非公開」の可視性しか持っていませんが、保護されていないパッケージは保護されていません。だからあなたはそれをエクスポートするか、呼び出しを「ハードコーディング」します。 – Zed

+1

しかし、なぜ静的にバインドされたコールxyz(Name) - > p()の場合にエクスポートする必要はありませんか。動的にバインドされているときにエクスポートする必要がありますか? 「私的な」可視性の観点から考えると、私は私的な範囲にいるのですが、そうではありませんか? – ottodidakt

0

それは(あなたが解決しようとしている問題)関数への動的呼び出しに依存していることを見てもう一つの方法であるとは限りませんプロセスとメッセージの受け渡しがErlangのコードを「並行処理指向言語」なので整理すると、シーケンシャル言語のイディオムを模倣するのではなく、選択受信でメッセージを渡すことができますか?あなたは何を望んでいるのかそれに基づいてカスタム返信を得ることができます。それは関数自体ではなく、各関数の結果に関するものです(さらに、メッセージの受け渡しなどの柔軟性とスケーラビリティなど)

Altライブラリモジュールから呼び出す場合に比べて、ハルプロセスは完全に自由ではないため、Erlangレベルのプロセスは安価です(特に、メッセージ通信が同じノード内にある場合)。 OSレベルのプロセスではありません。オーバーヘッドは、より重いスクリプト言語での動的な関数呼び出しとオブジェクトのインスタンス化に匹敵する(またはそれ以上)でしょう。

1

最も簡単な方法は、pとgをxyzとともにエクスポートすることです。次のように関数pをエクスポートした後

-export([xyz/1, p/0,g/0]). 

とgを呼び出すことができます。

1> sample:xyz(fun sample:p/0). 
"you called p" 
2> sample:xyz(fun sample:g/0). 
"you called g" 
関連する問題