2009-08-21 34 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"