Child modules draft feedback wanted

Richard A. O'Keefe <>
Mon Apr 3 06:34:38 CEST 2006


I have to leave in a few minutes, so there really isn't time
to respond to Romain Lenglet's points as they deserve.

	No, I am trying to solve that problem: removing the use of 
	-include, .hrl files, and -ifdef when those mechanisms are used 
	to select different alternatives in an architecture / 
	configuration.
	
But your proposal does not allow us to do that, thanks to records.

I also want to repeat that for Prolog and Erlang I have several times
(and in the case of Prolog, several times in the last week) heard a
"user" demand for some kind of hierarchical structure within a module.
"Child modules" were inspired by Ada, although they don't have much
in common with Ada 95 child modules.

	But my hypothesis (which I should have stated explicitly, sorry) 
	is that architecture alternative selection should be done at the 
	granularity of modules (not arbitrary pieces of code).

I agree.  I just don't think that all modules have to be the same.
In particular, I think that some modules *ought* to be private to
other modules.
	
	I am not trying to adapt the include mechanisms as you do (by 
	introducing the concepts of "parent" and "child" modules), but 
	rather to remove that concept entirely,

But a parent/child relationship is one of the things I am trying to ADD,
not take away.  I repeat, there are people who *WANT* hierarchical
structure within modules, and, if not taken to excess, I do not regard
that as unreasonable.  (The ersatz Java dotted module names, which I DO
regard as unreasonable, are an attempt to provide some kind of
hierarchical structure above the level of modules; I think replaceable
children can satisfy that need in a much better way.)

	> But this now GREATLY complicates the implementation.
	
	It can very easily be implemented by program transformation at 
	compile time. No need to change the runtime.
	
I completely fail to see how this can possibly be done at compile time.

Consider the following:

    -import(foo, [...]).

    f(M) -> M:g(42).

If M happens to be 'foo' at run time, then the call to M:g/1 should be
mapped to M':g/1, where M' is whatever foo is mapped to.  But that mapping
is private to this module, not global.  And if M happens to be 'goo' at
run time, then the call to M:g/1 should *not* be mapped to M':g/1.

What's even worse here is when the caller passes in 'foo' *intending to
refer to whatever 'foo' refers to IN THE CALLER*.

I think the single major difference between you and me here is that you
think module name indirection can be done easily at compile time without
any runtime changes, and I don't.

	Replacing a "logical" module name in module:call() statements in 
	the scope in a module, by an actual module name, can be done at 
	compile time very easily.
	
I don't believe this, and will take some persuading.

	> You are offering something as a feature that I regarded as a
	> serious problem to be avoided.
	
	I don't see where there is a serious problem.
	
That's because you think it is a trivial compile-time problem and
Id on't.

	> (1) I am trying to remove *FILE* names from the source
	> files. I don't see where you say anything about file names.
	
	Since module names are also file names, dealing with logical 
	module names instead of real module names removes file names 
	from the source files.
	
No, module names are NOT file names.  What's more, they shouldn't be.

Amongst other things, we have the problem that
      foobar
and   fooBar
are *different* Erlang atoms and therefore *different* as module names,
but under Windows foobar.beam and fooBar.beam are the *same* file name.
Since the criteria for establishing identity are different, module names
CANNOT be file names.

	As I understand it, the main use of -ifdef, etc. is to select 
	alternative architectures. Using an ADL, you would simply have 
	to write several specs.
	
Yes, but that could mean repeating hundreds of lines.
I'm thinking in terms of something like C/MESA.

	*Dependencies* (what is required) must be stated in a module's 
	source code, since they are very interdependent on the module's 
	implementation (you cannot change one without changing the 
	other).

	On the other hand, *bindings* should be stated outside, because 
	the architecture (the configuration) is a concern separated from 
	the modules implementation.
	
Complete agreement.

	Modules and their bindings form a "flat" graph: they do not 
	necessarily form a tree, or "hierarchy".
	
Nobody said they do so *necessarily*.  But we DO as an empirical
fact have a hierarchical structure of systems, applications, and modules,
plus hierarchical structure within modules that is not syntactically marked.

	> I am trying 
	> to design a principled replacement for -include AND I am
	> trying to meet a frequently expressed "need" for some kind of
	> hierarchical name scope WITHIN a single module.
	
	And this contradicts my basic principle (which I state in the 
	beginning of this email, sorry I should have stated this 
	before): configuration alternatives ("what can be required") 
	should be specified as functions in modules.

This contradiction does not exist.  The 'frequently expressed "need"
for some kind of hierarchical name scope WITHIN a single module'
has *NOTHING WHATEVER TO DO WITH* configuration alternatives.  I
believe that one mechanism can help with both needs, but they are
none-the-less separate and distinct needs.

	We already have 
	functions, and modules, and they can be used as units for 
	selecting configuration alternatives. We don't need to introduce 
	new concepts ("parent" and "child" modules) only for that 
	purpose.
	
But nowhere have I stated, nor is it even close to true,
that the concepts ARE new or are ONLY for that purpose.

	I agree very much with you.
	And my proposal does not replace all uses of -include / -ifdef, 
	but it solves at least the important problem of selecting 
	alternative implementations.
	
	I also agree with you, in that my proposal does not replace 
	-record.

Your proposal, as stated, DOES NOT HANDLE RECORDS.
There are therefore ALMOST NO uses of -include in the present
system which could thus be replaced.

	I think that it is a bad idea to try to specify a single 
	construct that would replace all actual usages of -include and 
	-ifdef: either the new construct will be as bad as what it 
	replaces, or it will not cover all usages.
	
This seems to me to be a matter of personal taste; I see no reason
why the claim should be true.

	Maybe you have arguments against that, but please write them. ;-)
	
No, "extraordinary claims need extraordinary evidence".  YOU are the
one saying that one good mechanism can't be enough, so it's you who
have the obligation to provide the evidence.

	I agree. But let's solve one problem at a time?!
	
I am sorry, but -record is the MAJOR problem.  If you want to solve
one problem at a time, you have to solve -record FIRST.  I have
already tackled that in two different ways:  "abstract patterns"
and "frames" alias Joe Armstrong's "proper structs".  Neither of
those has (yet) been adopted or is likely to be in the near future.
To move forward, we need to move forward with what we have, and
that means -record.

	Why not have a specific construct or convention to get record 
	information at a module level (not at a source code level, like 
	-record).

The Erlang/OTP support people have already made it plain that they
will not tolerate any replacement for -record that *requires*
cross-module inlining.

Trying to develop a solution that you know has no chance of being
adopted is simply an idle pastime like painting flowers on toilet paper
just before you use it.

Something that provides a kind of encapsulation, requires minimal
changes to the run-time system, and *still* allows the use of -record
with no cross-(full)-module inlining has *some* non-zero chance of
being useful.




More information about the erlang-questions mailing list