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