There are two parts to this answer. The first is that you probably don't want to use paramatized modules until you're quite proficient with Erlang. All they give you is a different way to pass arguments around.
-module(test_module, [Param1]).
some_method() -> Param1.
is equivalent to
-module(test_non_paramatized_module).
some_method(Param1) -> Param1.
The former doesn't buy you much at all, and very little existing Erlang code uses that style.
It's more usual to pass the name argument (assuming you're creating a number of similar gen_servers registered under different names) to the start_link function.
start_link(Name) -> gen_server:start_link({local, Name}, ?MODULE, [Name], []).
The second part to the answer is that gen_server is compatible with paramatized modules:
-module(some_module, [Param1, Param2]).
start_link() ->
PModule = ?MODULE:new(Param1, Param2),
gen_server:start_link(PModule, [], []).
Param1
and Param2
will then be available in all the gen_server callback functions.
As Zed mentions, as start_link
belongs to a paramatized module, you would need to do the following in order to call it:
Instance = some_module:new(Param1, Param2),
Instance:start_link().
I find this to be a particularly ugly style - the code that calls some_module:new/n
must know the number and order of module parameters. The code that calls some_module:new/n
also cannot live in some_module
itself. This in turn makes a hot upgrade more difficult if the number or order of the module parameters change. You would have to coordinate loading two modules instead of one (some_module
and its interface/constructor module) even if you could find a way to upgrade running some_module
code. On a minor note, this style makes it somewhat more difficult to grep the codebase for some_module:start_link
uses.
The recommended way to pass parameters to gen_servers
is explicitly via gen_server:start_link/3,4
function arguments and store them in the state value you return from the ?MODULE:init/1
callack.
-module(good_style).
-record(state, {param1, param2}).
start_link(Param1, Param2) ->
gen_server:start_link(?MODULE, [Param1, Param2], []).
init([Param1, Param2]) ->
{ok, #state{param1=Param1,param2=Param2}}.
Using this style means that you won't be caught by the various parts of OTP that don't yet fully support paramatized modules (a new and still experimental feature). Also, the state value can be changed while the gen_server instance is running, but module parameters cannot.
This style also supports hot upgrade via the code change mechanism. When the code_change/3
function is called, you can return a new state value. There is no corresponding way to return a new paramatized module instance to the gen_server
code.