Hot loading and preprocessor [was: Re: the Hopwood design process]

Kostis Sagonas <>
Wed Mar 15 11:33:10 CET 2006


I asked:
 > > How are records different than e.g. changing the types of data
 > > structures that some module obtains from some other module and
 > > manipulates?
   
and Richard A. O'Keefe replied:
 > This is like asking "how is a brick different from breaking an egg?"
 > One is a thing, the other is an activity.

Thanks for this clarification. Let me repeat my question in a way such
that grammar will not stand on our way:

  Currently, records are just syntactic sugar for tuples. What exactly
  is it that makes records different from tuples -- or for that matter
  lists, or any other data structure -- which are shared between modules?

Seems to me that the fundamental problem is not keeping track of
data structure dependencies across modules, not whether records are
implemented using the preprocessor or via some other mechanism.


 > The main issue is that Erlang is a language based on modules,
 > and records are not based on and do not respect modules.

I agree with the first part: "records are not based on modules".

The second part is totally meaningless though. There is nothing in
records that makes them "respect modules" or for that matter "not
respect modules". The issue is left totally up to how one programs.

 > If you obtain a data structure from some other module and
 > manipulate it, *as long as you use the functions exported from that
 > module for the purpose of such manipulation*, you should be OK.
 > (Until the module is revised and reloaded, and even then abstract
 > patterns and psi-terms can help a lot.)
 >
 > If you get a record from another module and manipulate it using
 > record syntax, you *have* to bypass the module system to do so.
 > Both this module and the other module must get the record
 > definition from something that IS NOT A MODULE.

I do not really see the *have* part, but even if true, my reaction to
this is: So what?

 > (Or both modules could have their own declaration for the record
 > type, which also counts as bypassing the module system.)

What exactly is wrong with the following way of coding? 

File "rec.hrl" defines the record and defines wrappers for its
accessor functions using the preprocessor. It is shared between
modules, as it should, because this is what header files are about.
Module "rec" defines the functions that create and update records.
Module "foo" calls the "rec" module to create a record and then uses
the preprocessor twice (once in the define and once in the #rec.b).

%------------------------ rec.hrl -----------------
-record(rec, {a,b}).

-define(rec__a(R), R#rec.a). 
-define(rec__b(R), R#rec.b).
%------------------------ rec.erl -----------------
-module(rec).
-export([new/0, update_a/2, update_b/2]).

-include("rec.hrl").

new() -> #rec{}.

update_a(R, Val) -> R#rec{a = Val}.
update_b(R, Val) -> R#rec{b = Val}.
%------------------------ m.erl -------------------
-module(m).
-export([foo/0]).

-include("rec.hrl").

foo() ->
  R = rec:update_b(rec:new(), 42),
  ?rec__b(R).
%--------------------------------------------------

I specifically used the preprocessor twice in the last line of foo/0
to illustrate the point that the preprocessor is really not to blame
for what is being discussed here -- as a matter of fact, it comes in
handy because it allows the accessor functions to be shared between
modules. (Although they could just as easily be part of "rec.erl".)

The fact that there is no mechanism to keep track of data structure
dependencies between modules and that modules can be reloaded on an
individual basis is really orthogonal to the record vs. abstract
patterns discussion and how these are implemented. In particular, the
preprocessor has absolutely nothing to do with it. This is my point.


Cheers,
Kostis




More information about the erlang-questions mailing list