Reflection in Erlang.
Fredrik Linder
fredrik.linder@REDACTED
Wed Jan 26 17:43:08 CET 2005
> -----Original Message-----
> From: owner-erlang-questions@REDACTED
> [mailto:owner-erlang-questions@REDACTED]On Behalf Of Héctor Rivas
> Gándara
> Sent: den 26 januari 2005 16:51
> To: erlang-questions@REDACTED
> Subject: Reflection in Erlang.
>
>
>
> Hi,
>
> One year ago somebody asked for a way to obtain info on a
> loaded module.
> The response were module_info/0 and module_info/1 funtions.
>
> My question now is if its posible to dinamicly impersonate
> an erlang module,
> in order to create an "stub" module. I want to construct an
> module from a
> interface definition, so I can do something like:
(a)
> StubModule = adaptor:getStub("anInterfaceId");
> Obj = anInterfaceId:createInstance();
> StubModule:method1(Obj);
> StubModule:method2(Obj, 1, 2);
>
> If there is no reflection the aproximation can be:
(b)
> Obj = adaptor:createInstance("anInterfaceId");
> adaptor:callMethod(Obj, method1, []);
> adaptor:callMethod(Obj, method2, [1,2]);
I'm not 100% into the earliest development of erlang, but (and perhaps a little more than you asked for):
One of my favourite usages of the behaviour feature is to write an behaviour definition module and then write a behaviour implementation in another module. The behaviour definition module *also* implement the exported functions, but with a Module argument as the first argument.
[my_behaviour.erl]
-module(my_behaviour).
-export([behaviour_info/1, my_func1/2, my_func2/3]).
behaviour_info(callbacks) -> [{my_func1, 1}, {my_func2, 2}].
my_func1(Mod, A1) -> Mod:my_func(A1).
my_func2(Mod, A1, A2) -> Mod:my_func(A2).
[my_behaviour_implementation.erl]
-module(my_behaviour_implementation).
-behaviour(my_behaviour).
-export([my_func1/1, my_func2/2]).
my_func1(A1) -> something.
my_fund2(A2) -> something.
The user code can then choose to either call:
my_behaviour:my_func1(my_behaviour_implementation, A1)
or
my_behaviour_implementation:my_func1(A1).
Using this design you could have the adaptor:getStub(...) return my_behaviour_implementation and later use that to make the calls.
adaptor:createInstance("anInterfaceId") -> my_behaviour_implementation.
This scheme works well iff the Obj is a singleton! I can think of two ways to remove the singleton requirement.
(1) Add a state. In this case is alternative (a) not possible. To make (b) work; switch the Mod to contain a state.
[my_behaviour.erl]
-module(my_behaviour).
-export([behaviour_info/1, my_func1/2, my_func2/3]).
behaviour_info(callbacks) -> [{my_func1, 2}, {my_func2, 3}].
my_func1({Mod, State}, A1) -> Mod:my_func(State, A1).
my_func2({Mod, State}, A1, A2) -> Mod:my_func(State, A2).
[my_behaviour_implementation.erl]
-module(my_behaviour_implementation).
-behaviour(my_behaviour).
-export([my_func1/2, my_func2/3]).
my_func1(State, A1) -> something.
my_fund2(State, A2) -> something.
(2) Dynamically create a module following these steps:
Have the adaptor:createInstance("anInterfaceId") function (exactly how to can be found in the archives of this mailing list):
1 - Write the code of the module relating to the specified interface *with* state information into a file.
2 - Compile that module (file) in run-time using the compile module.
3 - Load that module into the desired node(s).
4 - Initialize the module if necessary (especially if each object also is a process).
5 - Return the module name (as an atom).
Each new instance need a unique module name, consider using a descriptive basename and the erlang:node/0 function along with erlang:now/0 to generate this. Also make sure the newly compiled code exports the desired functions.
This enables the (a) alternative.
Good luck
/Fredrik
More information about the erlang-questions
mailing list