[erlang-questions] Parameterized module idioms
Paulo Sergio Almeida
psa@REDACTED
Tue Apr 20 13:25:38 CEST 2010
Hi all,
I have not used much parameterized modules, but was very delighted when
did do, and I think they gives us something, in practice.
Richard O'Keefe wrote:
> I pointed out that modules with parameters give us nothing
> that plain old closures don't, in response to which
Closures must be passed somehow, if they are to be used in a function.
If I am writing many functions which use some nonrelated parameters,
some closures are being passed around. That is already too much
pollution for my tastes.
>> Trivial, but requires a lot of boilerplate code and certainly isn't
>> any easier to understand or debug than parameterized modules. It also
>> becomes impossible to write a useful type spec if you use closures
>> like that.
>
> (a) Such boilerplate code as is required can be automatically generated.
If some code would need to be generated if I didn't have parameterized
modules, then parameterized modules already give me something.
Let's look at some examples (from a homemade "database" I wrote some
time ago).
The more simple use may be for substituting constants with something
calculated at runtime; e.g.
Instead of
need_dump(Tab, LogOps) -> LogOps > ?DUMPLIMIT * ets:info(Tab, size).
I can have
need_dump(Tab, LogOps) -> LogOps > DumpLimit * ets:info(Tab, size).
with no change in the interface of the function.
But it becomes much more interesting when modules themselves are used as
parameters of other modules.
The first version had a constant directory path defined and used by a
module pets_lib that served as a sort of general library. Then other
modules used pets_lib.
For example, a module pets_tm would have somewhere:
Res = pets_lib:delete_table(Tab),
How do I make the path (as well as many other configuration parameters)
a value chosen at runtime, with little effort in rewriting the code
which didn´t contemplate such possibility beforehand? Making pets_lib a
parameterized module. What is the impact of that on client code? A
simple change to:
Res = Lib:delete_table(Tab),
It looks pretty much the same, but now we have this Lib variable. If we
were using closures, the closure would have to be passed somehow (who
knows how many levels of invocations) until is was available to the
function which performs this invocation. But if the pets_lib
instantiation is a parameter of pets_tm, then I can use statements like
the above all over pets_tm by doing a simple:
:%s/pets_lib/Lib/g
and making pets_tm parameterized; e.g.
-module(pets_tm, [Lib, DumpLimit]).
Nothing much changes, code is basically reused, we are programming
mostly with plain old functions. The parameters that represent modules
can even have pleasant names, as we do not need to worry about module
namespace pollution in client code and we can rename modules easily
without that having much impact on client code.
Then we only need to glue modules together at service starting time; e.g.
start_link() ->
start_link(#pets_config{dir="PETS", gc={100,0.1,0.3},
sync_delay=1000}).
init(#pets_config{dir=Dir, gc={MT, CR, PR}, sync_delay=SyncDelay}) ->
process_flag(trap_exit, true),
pets_locker:start_link(),
Lib = pets_lib:new(Dir),
Tabs = Lib:init(),
(pets_gc:new(Lib, MT, CR, PR)):start_link(),
Inserters = 2 * erlang:system_info(schedulers),
LastTid = (pets_loader:new(Lib, ?FILE_READERS,
Inserters)):load_tables(Tabs),
(pets_writer:new(Lib, SyncDelay)):start_link(),
(pets_tm:new(Lib, ?DUMP_LIMIT)):start_link(LastTid),
{ok, nostate}.
(Ironically DumpLimit is still a define here in the "main". ;))
I think all this is nice and very practical. If languages like ML have
first class modules and that is ok, what is the problem in Erlang
adopting this nice looking concept?
Btw there is something which irritates me in the above: Having to write
parenthesis as in:
(pets_gc:new(Lib, MT, CR, PR)):start_link(),
it should be possible to just write:
pets_gc:new(Lib, MT, CR, PR):start_link(),
(and I profoundly hate the "new" keyword, but that is another story)
Best Regards,
Paulo
More information about the erlang-questions
mailing list