Promised unit "paper"
gjacobs at bioinfotools.com
Mon Mar 10 01:34:28 CET 2003
Well, I promised that I'd write up a brief account of what I really
meant. Unfortunately I'm going to have to let it slip a little as I
am extremely busy. Hope this rushed effort make its clearer, not more
confusing! Looking at it briefly, if anything its redundant as all
this seems to have already been covered, but all the same... I did
promise more examples, which I have to admit I'm out of time for...
maybe another week.
Anyway, on with the show.
Basically identical to BP units:
<export declaration part>
uses whatever, somemore;
The difference lies in the way the elements are used, not the syntax.
Because of this, I suspect if this were to be implemented, a compiler
switch such as the one Chief suggested would be appropriate. No new
keywords, Frank! ;-)
There are no different types of uses clauses; they always do the same
thing: import stuff. The difference is what happens once the stuff is
The implementation doesn't import the interface, it only checks
against the interface's declaration part. So it has to import its own
stuff for itself; more on that in a mo'.
B. Independence of action of the interface and implementation sections
Firstly, let's clarify the flow of information of interface and
implementation sections as this seems to have caused confusion
amongst some people. Conventional units effectively work such that
the declarations in the interface are imported into the
implementation section of the same unit.
Here, interface exports all of its contents to other units. Its
declarations are *checked* against those of the implementation
section. The implementation section has its own definitions; it does
not import those from the interface for its use. As a consequence, it
does not import the uses present in the interface section. Right?
You *could* have the declarations in the interface imported as in BP
units, but I believe it works best - for these types of units - if
the two are more-or-less independent, bar the checking of the
declarations. If you do have the implementation import the stuff from
the interface, you now are asking for trouble with the uses clauses.
Each section separately imports (uses) any other units that they
need. This isn't checked across the interface/implementation
boundary; only the declaration part is.
*Everything* in the interface is exported, including any imported
units (via uses). One rule, no exceptions. The interface section is a
container saying that "these things ought to be exported".
Everything in the implementation section is private.
An interface is free to import (and hence re-export) any unit it
feels relevant. It could for example import a related unit which is
not needed in the implementation of the current unit, but which is
useful for the users of the current unit in some way.
The interface section will, of course, have to import the units
needed to satisfy the declaration part of the interface. This has the
effect that users of the current units get these dependencies "for
free". This can work well, provided that developers of lower-level
units don't place a lot of things into the interfaces that really
aren't needed to be there - which they ought not to be doing anyway.
Put in another way: the current unit's interface looks after the
"required definitions" on behalf of any users of the current unit by
exporting those that are needed. (To do this with more control - a
good thing I think - you really need the ability to import only
subsets of an interface.) We've already discussed how this can shield
higher-level units from re-organisation of code in lower-level units.
The implementation is free to import units it needs that are not
needed to satisfy the interface declaration part or needed by the
user of the current unit. It could, for example, import units which
are effectively private to the implementation of the current unit,
such as one we decided to bundle all system-dependent elements into
or a unit with some obscure internal manipulations which are
necessary for the implementation but really ought to be hidden from
Because of the way things work, there will almost always be a uses in
both the interface and the implementation, unlike in BP units where
you can use only only one uses in the interface section and rely on
the implementation section picking this up. Having the uses in the
interface imported by the implementation imposes restrictions on the
interface and if you left things that way the idea of re-exporting
interfaces of imported units would awkward. I think this is where
some people's early complaints of "re-exporting everything" come from
(i.e. they are thinking of a single uses in the interface section
importing everything needed for both the interface declarations and
the implementation. I wouldn't want all the stuff for the
implementation section re-exported either and with the two uses you
don't have to.). You really need the interface and implementation
sections to be more independent and you need a uses clause in both
(so that they are independent) to make this work well.
You could mimick the equivalent of the BP uses situation, by allowing
the result of a uses clause outside both the interface and
implementation sections to be 'read-only' to both sections, but
personally I think this could be confusing - ? (You might have
problems if the interface and implementation are placed in two
separate files - haven't got time to think about this right now.) I'm
really not sure what to do about the possibility of a uses clause
outside of both sections, but it strikes me as being inconsistent
with the rest of the approach.
While you could introduce an export clause of some sort, they aren't
really necessary under this scheme and it seems easier on the
programmer to just remember that everything in the interface is
exported, including what is brought in through uses. Its a simple
enough rule. And no new syntactic elements, Frank! (But perhaps some
of the behaviour differences are annoying instead?)
BTW, I don't have experience with use of several interfaces for one
module as Frank mentioned in a earlier post (he says this is possible
in EP). If anyone has any comments on this, I'd be happy to hear them.
Not recommended in general, but on rare occasion useful - you can
allow users to optionally relax the type checking across the
interface/implementation barrier (comparing the implementation's
definitions to declaration part of the interface) to allow explicit
recasting of types for the rare occasions this is useful. This isn't
possible if the interface is imported into the interface section. Not
exactly a feature to rest a debate on, though ;-) The inheritance is
the key thing; this is just a minor aside.
C. Circular references.
Skating out on thin ice here...
If a unit's interface has already been imported, a re-importing of it
is redundant (unless you allow importing only parts of an interface,
but let's keep this simple for now). This ought to be able to break
the deadlock -- ? Ditto for the initialisation code.
I have to get back to work, so this is where I stop. Sorry... or
perhaps you're grateful?! ;-)
Grant Jacobs Ph.D. BioinfoTools
ph. +64 3 476 1820 (office, after 10am) PO Box 6129,
or +64 25 601 5917 (mobile) Dunedin,
gjacobs at bioinfotools.com NEW ZEALAND.
Bioinformatics tools: deriving knowledge from biological data
Bioinformatics tools - software development - consulting - training
Check out the website for more details: http://www.bioinfotools.com
The information contained in this mail message is confidential and
may be legally privileged. Readers of this message who are not the
intended recipient are hereby notified that any use, dissemination,
distribution or reproduction of this message is prohibited. If you
have received this message in error please notify the sender immed-
iately and destroy the original message. This applies also to any
More information about the Gpc