Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a module dynamically in Erlang?

Tags:

erlang

Assume I have two modules a.erl and b.erl. Both modules contains the same functions ( in Java I would say "both classes implement the same interface" ). In module "c.erl" I want to have a function that will return module "a" or "b" ( depends on the parameter )

Here is what I want to have in module c.erl

-module(c)

get_handler(Id) ->

 % if Id == "a" return a

 % if Id == "b" return b

test() ->

 get_handler("a"):some_function1("here were go for a"),

 get_handler("a"):some_function2("aaaa"),

 get_handler("b"):some_function1("here we go for b")

How can I make this work? I am relatively new to Erlang and don't know how to do it. In Java it would be very obvious, because you just return new instance of the class.

like image 385
cactus Avatar asked Jan 03 '16 16:01

cactus


2 Answers

Just have get_handler/1 return the module name as an atom, and then use it to call the desired function:

(get_handler("a")):some_function2("aaaa"),
(get_handler("b")):some_function1("here we go for b").

Note that you need parentheses around the call to get_handler/1 in this case.

A simple version of get_handler/1 for modules a and b could be:

get_handler("a") -> a;
get_handler("b") -> b.
like image 183
Steve Vinoski Avatar answered Nov 16 '22 07:11

Steve Vinoski


If you have an atom in a variable you can use it as a module name.

So, you could define c:get_handler/1 like this:

get_handler("a") -> a;
get_handler("b") -> b.

Your c:test/0 looks ok, except you need extra brackets, like this:

test() ->
    (get_handler("a")):some_function1("here were go for a"),
    (get_handler("a")):some_function2("aaaa"),
    (get_handler("b")):some_function1("here we go for b").

Then in modules a and b just define a some_function1/1 and some_function/2, for example:

some_function1(Str) ->
    io:format("module ~s function some_function1 string ~s~n", [?MODULE, Str]).

some_function2(Str) ->
    io:format("module ~s function some_function2 string ~s~n", [?MODULE, Str]).

Edit: You should possibly also define a behaviour if you're going to do this sort of thing BTW, which would mean you would declare in modules a and b something like this:

-behaviour(some_behaviour).

Then create module some_behaviour something like this:

-module(some_behaviour).
-callback some_function1 (String :: string()) -> ok .
-callback some_function2 (String :: string()) -> ok .

This means any module like a and b that declare that they support the behaviour some_behaviour must define those functions, and the compiler will speak up if they don't. The types of the parameters and return value are also defined here for static analysis, etc.

like image 23
Michael Avatar answered Nov 16 '22 07:11

Michael