[erlang-questions] Parameterized module initialization

Loïc Hoguin essen@REDACTED
Thu Jun 28 15:32:54 CEST 2012


On 06/28/2012 02:00 PM, Ulf Wiger wrote:
>
> On 28 Jun 2012, at 13:17, Loïc Hoguin wrote:
>
>> But I'm not talking about the result. I'm talking about how the same code can call different arities depending on the contents of a variable. Var:func() doesn't always call a function of arity 0, as you'd read it instinctively, you need to look elsewhere to be sure of what is really happening. The syntax Var:func() has two meanings instead of just the one we expect.
>
> Sure, but with the gen_server, it's just a layer of indirection or two,
> and then you have the same problem.
>
> In the first step, it's easy enough:
>
> I call an API function, which (normally) immediately maps to
> a call to gen_server:call(Server, Req).
>
> How do I know which code Server will end up calling?
>
> Well, by convention, we keep the corresponding handle_call()
> in the same module. Otherwise, I'd have to try to resolve it, perhaps
> at runtime, or through a wider code search, to figure out which
> callback Server actually uses.
>
> Once I've found the right handle_call(), I still have to pattern-match
> mentally on the arguments to find the right clause. *Then*, I know
> which code actually gets called as a result of my initial operation.
>
> The fact that you can't easily pair sends with receives in Erlang code
> without resorting to convention is a problem, but convention is not
> to be knocked, of course. That we *can* easily map function calls
> is a feature, and a very good one. It isn't obvious that we should
> add language features that start eroding this feature.

Right, actually more things can go wrong with gen_server, the process 
may not even be alive anymore when you do the call. But all these issues 
are abstracted by gen_server, and unless you did something really weird 
you always get a reply. So the API function call stays intuitive, you 
just have many different possible return values.

If your module exports doit/0 and you call it unknowingly with 
{module,123}:doit(), you end up with a crash. Not a return value. Or 
worse it can be doit/1 that is called, which may not even crash and just 
store your value somewhere ready to crash your code much later down the 
road.

What is less intuitive and requires knowledge is the gen_server code 
itself, but as you say convention helps. The big difference however is 
that gen_server isn't an element of the language itself, unlike tuple 
calls. You can always choose to not use gen_server and write gen_better 
instead, but you're stuck with the language.

-- 
Loïc Hoguin
Erlang Cowboy
Nine Nines



More information about the erlang-questions mailing list