tags:

views:

298

answers:

2

I can see why parameterised modules are used so much, as they allow us to do things like:

X = y:new("param").

X:action1().
X.get_property():

: which feels very OO. However, this is only an experimental feature in Erlang and I hear it may be removed, so I need to find an alternative.

+1  A: 

Why can't you use the usual way i.e. send message to a (registered) server process associated with a module?

The message in question can be whatever you want of course e.g. configuration etc.

What problem are you trying to solve that can't be handled in such way?

jldupont
Take for example a client library for a key value store:{ok, C} = lib:client_connect("ip address").<br>C:list_keys().<br>C:get(Value).<br>: seem very convenient.
Zubair
there's not that big a difference in doing: lib:list_keys(C) lib:get(C,Value). and you know where the code which is executed is to boot!
Lukas
Your right. I have to not use that feature.
Zubair
Also, the actor based code to do this is about 5 times longer and much more unreadable.
Zubair
@Zubair: I guess it is application/implementation dependent.
jldupont
+7  A: 

Parametrised modules are nothing but a shortcut on the first argument of a function. See these two examples:

-module(y, [Name,Age]).
-compile(export_all).

action1() -> io:format("Hello, ~p!~n",[Name]).

get_age() -> Age.

Run it:

1> c(y).
{ok,y}
2> X = y:new("Fred",22).
{y,"Fred",22}
3> X:action1().
Hello, "Fred"!
ok
4> X:get_age().
22

Now without parametrized stuff:

-module(y).
-compile(export_all).

action1([Name,_]) -> io:format("Hello, ~p!~n",[Name]).

get_age([_,Age]) -> Age.

Running it:

1> c(y).
{ok,y}
2> X = ["Fred",22].
["Fred",22]
3> y:action1(X).
Hello, "Fred"!
ok
4> y:get_age(X).
22

The biggest 'advantage' of parametrized modules is that you shift the burden of carrying state from a variable to a module name. This is in appearance much simpler to someone not used to 'the Erlang way', but it clashes with conventional styles of code.

It's not just a question of being experimental or not. You throw out referential transparency and the semantics to immutable variables become a bit weird. A good example of this is to imagine you add the following functions to a parametrized module:

ret_fn() -> fun(Age) -> Age + 5 end.

When compiling the module, you get the warning ./y.erl:8: Warning: variable 'Age' shadowed in 'fun'. This is warning you that you are using the name of a predefined variable within the head clause of an anonymous function. However, a quick look at the ret_fn/0 function shows absolutely NO sign of where that variable is from.

Now imagine that you use the variable Name for any other purpose; you will get a run time error telling you ** error: no match of right hand side value < ... >.

The point I'm making is that parametrized modules reduce the amount of typing you need to do at the expense of logical simplicity. Not just for you, but for any other Erlang programmer to work on your code.

On top of that, tools like dialyzer, TypEr, tidiers and whatnot have no guarantee to support these idioms. These tools are pretty useful, too! Don't dismiss them. (Edit: newer versions of Erlang (R13B04+) now guarantee that support)

The best alternative to parametrized modules is to avoid them and use what every other Erlang programmer outside of mochiweb is using.

I GIVE TERRIBLE ADVICE
I thought about it and you are right. I am just being a lazy bast#$rd by using parameterized functions, and I should not use them. But what about all the systems that use them? Why are they using these undocumented features
Zubair
I don't really know why they use it. Other people from the #erlang channel on freenode don't really know either. I think it might have been done to make it conceptually simpler for the user of the libraries. I'd argue that the simplicity of doing `my_func(Mod) -> Mod:Call(Args) end`, is not a huge gain when compared to `my_func(Mod,X) -> Mod:Call(X,Args) end`. Add to that the problems I mentioned in my answer and I can't think about much other than bad decisions or wanting to experiment with code.
I GIVE TERRIBLE ADVICE
I didn't however understand what you said about "ret_fn() -> fun(Age) -> Age + 5 end.". Is this because "Age" was passed in as a paramter to the module?
Zubair
Shadowing is what happens when you have a variable in the current function's scope that you bind in a new function's head: `X=2, fun(X) -> X + 1 end` will warn about shadowing because the `X` inside the anonymous function is *not* the one defined to be equal to 2. The compiler warns you in case this was an error.In the case of `ref_fn/0`, the variable `Age` is implicitly passed to the function. Therefore, you get shadowing warnings even though the variable doesn't appear to be declared in the source.
I GIVE TERRIBLE ADVICE
Ah ok, yes, thanks for the explanation of shadowing.
Zubair
I want to add to the record that Dialyzer and other tools have begun supporting parametrized modules officially. That part of the argument no longer holds.
I GIVE TERRIBLE ADVICE
So, I GIVE TERRIBLE ADVICE, don't hold back. Tell us what you *really* think of parametrized modules! :D
JUST MY correct OPINION
They annoy the hell out of me and I dislike having to consider two different manners of writing simple stuff such as function calls in a small language like Erlang
I GIVE TERRIBLE ADVICE