在Erlang中,如何动态调用函数?

时间:2009-08-21 06:58:49

标签: erlang

我想用要调用的函数的名称调用xyz。

-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>

5 个答案:

答案 0 :(得分:23)

你必须输出p和g是正确的。然后,您可以使用apply / 3来调用它。

erlang:apply(sample, p, [])

只有fun-values可用于Fun(...)语法。你传递的是原子值。当错误消息消失时,原子是一个“坏函数”。你可以做类似的事情

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

然后继续打电话

Fun = xyz(p),
Fun()

答案 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"

答案 2 :(得分: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},
 {..., ...},
 ...]

然后,您可以将事件绑定到函数。 (不用说,还有更多的东西。

答案 3 :(得分:1)

最简单的方法是尝试将x和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"

答案 4 :(得分:0)

另一种看待它的方法是(取决于您正在解决的问题)对函数的动态调用不一定是正确的方法。鉴于进程和消息传递是你在Erlang中组织代码的方式,因为它是一种“并发性语言”,也许你可以只使用选择性接收的消息传递而不是模仿顺序语言的习语?发送您想要的消息并根据该消息获取自定义回复。毕竟,这是关于每个功能的结果,而不是功能本身。 (另外还有消息传递的灵活性和可扩展性等)。

虽然与从库模块调用相比,进程并不是完全免费的,但是Erlang级进程非常便宜(特别是如果消息通信在同一节点内)。它们不是操作系统级别的流程。在较重的脚本语言中,开销与动态函数调用和对象实例化相当(或更好)。