2009-08-21 78 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

我二郎山知識是接近於零,但我想你需要導出P(以及可能的克,如果你想以使用它)。 – balpha 2009-08-21 07:08:22

回答

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

謝謝。我現在有這個: -module(樣本)。 -export([xyz/1,p/0,g/0])。 xyz(Name) - > apply(sample,Name,[])。 p() - >「你叫p」。 g() - >「你叫g」。我可以做: 26> c(sample.erl)。 {ok,sample} 27> sample:xyz('p')。 「你叫p」 28> sample:xyz(p)。 「你叫p」 29> sample:xyz('g')。 「你叫g」 30> sample:xyz(g)。 「你叫g」 但是沒有導出這些函數的方法嗎?我不希望它對模塊用戶可見。似乎無法讓它與apply/2一起工作。當然,我是一個erlang新手 – ottodidakt 2009-08-21 07:53:50

+1

您可以使用模式匹配對您的呼叫映射進行硬編碼,也可以導出您的函數。 – Zed 2009-08-21 08:35:05

+0

「泄漏」未導出函數的唯一方法是返回引用它的有趣值。就像我顯式的xyz/1函數返回一個有趣的值。 – Christian 2009-08-21 10:41:15

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

雖然這在技術上是做到這一點的一種方式我認爲這個問題更多地針對erlang語言中的動態調用函數的機制。應用功能是他正在尋找的答案。 – 2009-08-22 02:17:40

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 2009-08-21 09:09:12

+0

以下是預定義的宏:http://erlang.org/doc/reference_manual/macros.html#7.3。不幸的是,Erlang只具有「公共」和「私人」可見性,但沒有受到保護和包裝保護。所以你要麼導出它,要麼「硬編碼」這些調用。 – Zed 2009-08-21 09:21:27

+1

但是爲什麼我不需要在靜態綁定調用xyz(Name) - > p()的情況下導出。並且在動態綁定時需要導出?根據「私人」知名度思考,我在私人領域,我不是嗎? – ottodidakt 2009-08-21 10:30:48

0

另一種方式來看待它是(取決於你解決問題),動態調用函數的不一定是考慮到流程和消息傳遞是你在Erlang中組織代碼的方式,因爲它是一種「面向並行的語言」,也許你可以使用消息傳遞與選擇性接收而不是模仿順序語言的習慣用法?發送消息你可以根據自己的想法獲得自定義答案,畢竟它是關於每個函數的結果,而不是函數本身(另外還有消息傳遞的靈活性和可伸縮性等)

Alt與來自庫模塊的調用相比,hough進程並非完全免費,Erlang級別的進程非常便宜(特別是在消息通信位於同一節點內時)。他們不是操作系統級別的進程。這些開銷與較重的腳本語言中的動態函數調用和對象實例化相當(或更好)。

1

最簡單的方法是嘗試導出p和g以及xyz。

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

後導出的函數P和G可以如下叫:

1> sample:xyz(fun sample:p/0). 
"you called p" 
2> sample:xyz(fun sample:g/0). 
"you called g"