[erlang-questions] Re: Will parameterized modules become an official part of Erlang?

John Hughes <>
Tue Feb 23 14:55:04 CET 2010



>> The reason is that we need to supply a call-back module implementing a
>> behaviour to a generic module like gen_server or gen_fsm, and the 
>> callback
>> module needs access to parameters that aren't fixed. So we use a
>> parameterised call-back module and pass that to the generic one. This is 
>> the
>> same kind of example that motivated Richard Carlsson's paper in the first
>> place... and there isn't any other good way of solving the problem. 
>> Making
>> the parameterised module into a gen_server instead, which has been
>> suggested, isn't a good solution in this case because it's not
>> reentrant--you can then only have one "instance" of the parameterised 
>> module
>> at a time. What if you need more?
>
> I'm not sure I fully understand all of this, but couldn't you just
> spawn more servers/processes?

Well, no.

I'm assuming a situation in which a generic module is fixed... maybe it's 
gen_server or gen_fsm in the OTP libraries, or maybe it's the eqc_statem 
module we use for testing state machines with QuickCheck. In either case, 
the generic code contains calls to callback functions which look like 
M:handle_call(...Params...), where M is the module name I pass in. I'm not 
going to change those calls--they're part of the published interface of the 
generic module.

Now, when I use a parameterised module, then M will be something like 
my_parameterised_module:new(ModuleParams), and of course I can construct

    M1 = my_parameterised_module:new(ModuleParams1),
    M2 = my_parameterised_module:new(ModuleParams2),
    M3 = my_parameterised_module:new(ModuleParams3)

and use them all at the same time. If my parameterised module implements the 
gen_server behaviour, for example, then I could create servers running the 
same code with different ModuleParams at the same time. What happens 
implicitly is that the value of M1 for example is a tuple 
{my_parameterised_module,ModuleParams1}, so the module parameters are 
carried with the module name to the point of call in the generic code.

Now the idea of replacing a parameterised module by a gen_server is based on 
saving the ModuleParams as the state of the server, so that they don't need 
to be supplied on each call. So now I can just call 
my_parameterised_module:foo() instead of M1:foo(), and the foo function can 
pick up ModuleParams1 from the server state. Of course, I could spawn 
several processes all running the same code with different states--but how 
would I tell the generic code which process to talk to? All I can do is pass 
in my_parameterised_module as the module name, then generic code will call 
my foo function, and then I have to somehow figure out which process to talk 
to, in order to pick up the right state. There's no information available to 
enable me to do so. That's why this idea works fine for a single process 
(just register it with the module name), but fails as soon as you want to 
support multiple instances.

I think you're imagining changing the calls in the generic code--passing a 
Pid as an extra argument, for example. Of course, if you do that, then you 
can use multiple processes to represent multiple instances. But now you're 
not reusing the generic code any more. With parameterised modules, we don't 
NEED to change the generic code at all, which is a big advantage.

John 



More information about the erlang-questions mailing list