[erlang-questions] Parameterized module idioms

Richard O'Keefe ok@REDACTED
Fri Apr 23 05:58:21 CEST 2010


A module with parameters is basically a surpassingly strange
way to write a function that returns a record of functions.

Right now, we can do exactly that:

     new(V1, ..., Vk) ->
	#record{
	    f1 = fun (...) -> ... end,
             ...
	    fm = fun (...) -> ... end
	}.

This thing, which I regard as an aggregate of closures,
can be passed around (just as an instance of a module with
parameters can), and the functions can be invoked:

	R#record.fi(...)

There are precisely two differences between this application of
the closure idea and modules with parameters.
(A) functions defined in the record like that cannot be recursive
(B) the invocation doesn't look like a remote function call.

We could make it look _more_ like a remote function call if
only my "frames" proposal were adopted, a proposal which has been
around for several years and addresses a lot of issues, and which
has the merit of being basically the same as Joe Armstrong's
"proper structs" proposal.

With frames, we'd write

     new(V1, ..., Vk) ->
	<{ f1 ~ fun (...) -> ... end
	 , ...
	 , fm ~ fun (...) -> ... end
	}>.

We now add one new feature:
    if E0 evaluates to a frame,
    and F is an atom
    and F is a key in the frame E0
    then E0:F(E1, ..., En) means
	case E0 of <{F ~ Fun}> -> Fun(E1, ..., En) end

This fixes (B).

We can fix (A) without requiring cyclic data structures in the
VM with a change to that definition:

	case E0 of V0 = <{F ~ Fun}> -> Fun(V0, E1, ..., En) end

and then we'd have to write

	<{ f1 ~ fun (M, ...) -> ... M:fk(...) ... end
          , ...
	 , fm ~ fun (M, ...) -> ... M:fj(...) ... end
	}>

which is a bit of a pain, but doable.

My argument here is
  - we want frames for a lot of other reasons,
  - once we have frames, they can do what modules with parameters do
  - modules with parameters can't do all the things frames can
  - so who needs modules with parameters?

One thing that's easy with frames is to check that
all the functions we want are there:

     client(Frame ~ <{ f1 ~ F1, ..., fk ~ Fk }>, ...)
       when is_function(F1, n1), ..., is_function(Fk, nk) ->
	... use Frame ...




More information about the erlang-questions mailing list