[clean-list] Comments on the module system

Fabien Todescato f.todescato@larisys.fr
Fri, 26 Jul 2002 18:21:47 +0200


Hi Marco, please let me state my reasoning explicitly, that motivates my
opinion on namespaces.

*	Assume <namespace> is an identifier for some namespace in a program.
The uses of the <namespace> identifier boils down to the following three
cases :

*	Assigning a freshly defined entity to an <identifier> within the
scope of the namespace, for example by writing :

		within listNameSpace
		  map	:: (.a -> .b) ![.a] -> [.b]
		  ...definition of map...

		In the above, the 'within <namespace>' statement is used to
introduce the scope of the namespace. Let's call that the scope the
'defining scope' of the namespace.

*	Using in an entity definition an explicitly qualified identifier
referring to some entity defined within the scope of some namespace. For
example :

		twiceMap :: ( a -> a ) [ a ] -> [ a ]
		twiceMap f l = listNameSpace::map ( f o f ) l

		In the above, the identifier 'listNameSpace::<identifier>'
is the explicitly qualified identifier.

		That use of qualified names is not supported by the current
Clean module system where one cannot writes <module>.<identifier>.

*	Using import statements to import identifiers from a namespace in
the current scope :

*	Explicit import statements : 

			using listNameSpace // Import all identifiers

			twiceMap :: ( a -> a ) [ a ] -> [ a ]
			twiceMap f l = map ( f o f ) l // 'map' Really
refers to 'listNameSpace::map'

*	Implicit import statements :

			from listNameSpace using map // Import 'map' only.

			twiceMap :: ( a -> a ) [ a ] -> [ a ]
			twiceMap f l = map ( f o f ) l // 'map' Really
refers to 'listNameSpace::map'

		These uses are similar to the import statements for the
current Clean module system.

*	In Clean, modules are the basic compilation unit. That is, any
identifier used in a compileable program must be defined in some
implementation module, and may be declared in some definition module.

*	The above rule must hold for namespaces identifiers.

*	Now the interesting point is to consider the interaction of
namespaces and modules. I see the following cases :
*	A.Defining a namespace :
*	1.The defining scope of a namespace is included within the defining
scope of a module. That is, if  the <namespace> identifier is exported by
both modules A and B, then :

			import A
			import B

			will cause a name clash on the <namespace>
identifier.

*	2.The defining scope of a namespace may span several modules. That
is, if  the <namespace> identifier is exported by both modules A and B, then
:

			import A
			import B

			will not cause a name clash on the <namespace>
identifier.

			Somehow the set of definitions intoduced in the
definining scope of the namespace in the module A and in the defining scope
of the namespace in the module B should be merged.
			This is the kind of flexibility you are asking for.
*	B.Using a namespace :
*	1.The identifier referring to the namespace must have been imported
somehow, by importing a module defining that namespace.
*	2.The identifier referring to the namespace need not be imported.

*	In case A.1 you cannot extend a namespace without touching the
corresponding module. This is not what you want. So let's rule this out now.
*	Case A2 allows for the extension of a namespace without touching
existing modules.
		In case A.2 we have to consider the subcases B.1 and B.2.
*	Cases A.2 & B.1 :
			If a namespace may span several modules, we need
somehow an arbitrary rule to know which module must be imported in order
that the namespace identifier be imported.
			Assume that it is enough to import one module with a
'within <namespace>' clause to import the <namespace> identifier.
			It is not reasonable to assume that the compiler
infer the modules we want to import, where all the definitions of a
particular namespace are located. Thus, the actual set of identifiers that
the compiler will allow to be visible in the namespace scope depends on a
list of imported modules that the programmer must somehow specify.
			The meaning of a namespace identifier used in a
module then depends on the context of compilation of that module, and cannot
be deduced from the analysis on the text of that module only.
*	Cases A.2 & B.2 :
			If the identifier of a namespace need not be
explictly imported, we rely on the compiler and the current compiling
context to give a meaning to the identifier. This is the same conclusion as
above.

Here is my line of reasoning. Based on this I consider that namespaces are
an unnecessary complication. :)

Essentially the only thing that the module system lacks IMO is the use of
qualified names <module>.<identifier> that would allow us to override the
default scoping rules.

Now, it may well be that I have missed some essential point in your proposal
for namespace :)

Kind regards,

Fabien

> -----Message d'origine-----
> De:	Marco Kesseler [SMTP:m.wittebrood@mailbox.kun.nl]
> Date:	vendredi 26 juillet 2002 16:49
> À:	f.todescato@larisys.fr
> Cc:	clean-list@cs.kun.nl
> Objet:	RE: [clean-list] Comments on the module system
> 
> Hi Fabien,
> 
> >	Consider for example the case that one wants to extend some 
> >	'standard' namespace with new definitions. In such a case it is 
> >	probably unwise to
> >	touch the original implementation modules, even if one does have the
> >	sources.
> >
> >Well, I don't know what Marco exactly means when he says to 'Add' a
> >definition to a 'namespace'. If 'namespaces' are such that definitions to
> >them can be 'dynamically' 'added' during the very process of compilation,
> >then the problem arises that the semantics of 'namespaces' is no longer
> >declarative. That is, it may be no more possible to infer the meaning of
> a
> >'namespace' from its text alone.
> 
> I am afraid that I do not understand. Function names are also 
> 'dynamically'
> 'added' during the process of compilation. Namespaces are just a way of
> _declaring_ names in a particular named set. Same as if you would 
> prefix each function name with a 'namespace' name, only without the 
> need to write down the
> namespace each and every time.
> 
> I could envisage a system in which you have to declare namespaces 
> before you can put function names in them. I am not sure whether that 
> would buy you much.
> 
> >Would this not be a blasphemous feature for a functional programming
> >language ? :)
> 
> No, certainly not more than overloading.
> 
> >Also, speaking from the viewpoint of software engineering, the Clean
> module
> >type system already allows for the kind of flexibility you are asking
> for.
> >Since imports are transitive in Clean - to be convinced of this read the
> >StdEnv.dcl - you can extend the set of identifiers exported by a module
> in a
> >relatively safe manner : just add an import clause. Say for example you
> want
> >to customize the StdEnv module/namespace with some new definitions of
> your
> >own in a myDefinitions module : just add import myDefinitions in StdEnv
> and
> >you're done - providing no name clashes occur -. This is certainly not as
> >flexible as what you hint at, but IMO safer.
> 
> Changing the StdEnv module counts as changing existing modules and in 
> my opinion this is bad, because you would have to do this each time a 
> new version of StdEnv gets releases.
> 
> Now, if all definitions imported by StdEnv.dcl can be referred to as 
> StdEnv.function (or similar) this seems equivalent with the 
> namespaces as I proposed. This - if this is what you mean - seems to 
> suggest however, that you must import StdEnv entirely via importing 
> StdEnv.dcl. I would rather just import the functions that I actually 
> need. Apart from this, there are some confusing practical problems 
> associated with it I think.
> 
> I am totally at a loss, why my namespace proposal would be unsafe.
> 
> >Personally, I consider adding namespaces entities to the already existing
> >module system would introduce unnecessary complications. As I see it,
> having
> >'namespace' coupled to module enforces a sound discipline of design.
> 
> As I see it, the module system has nothing to do with namespaces. So, 
> a 'sound' set of modules (whatever that is) does not automatically 
> lead to a sound set of namespaces. I would rather properly design the 
> set of namespaces.
> 
> >Now, my own preferences would be to allow for the use of qualified names
> of
> >the form <module>.<identifier> to gracefully handle the problem of name
> >clashes.
> 
> The problem I have with this, is that you have to run through all of 
> your code as soon as you think it is better to move 'identifier' to 
> some other module. Such a scenario is not unlikely.
> 
> >Another quite interesting functionality - as may be found in ADA - is the
> >possibility to rename imported identifiers locally in the module where
> they
> >are imported. Say, for example, to import 'or' from 'StdEnv' and locally
> >rename it as 'booleanOr', we could write a clause : 'from StdEnv import
> or
> >as booleanOr'.
> 
> Technically, this would work but:
> - with proper namespaces you probably do not need it
> - I would rather just assume that the original names are sensible 
> enough, so that I do not have to come up with some (contrived) new name.
> 
> regards,
> Marco