[fpc-pascal] child units (was: dot within unit file name)
Vinzent Hoefler
JeLlyFish.software at gmx.net
Tue Jan 22 08:51:28 CET 2008
On Monday 21 January 2008 18:45, Marco van de Voort wrote:
> > I think it would be fantastic if Free Pascal could add child units
> > as a language extension (of course this would reduce portability --
> > although on the other hand it might make porting Ada programs
> > easier). It's difficult trying to describe the benefits to someone
> > who has never used them (how do you know you're missing something
> > if you've never used it and therefore never felt a need for it?)
>
> I've used Modula2, and know nested modules. However I haven't missed
> them.
Well, I've missed them. (Although I don't remember Modula-2 too well, so
I can't say how much similar they are to Ada's child packages).
But child packages are really great for extending and adding
functionality without even touching existing source code.
> I have missed opague types and forcedly qualified importing (from
> M2)
Well, I miss them too. As I'll show you in a moment that they even go
hand in hand with child packages.
> M2 doesn't have the nested module "put in arbitrary other file"
> system though. Such system would have the same problems with M2 as
> with Pascal.
Well, you'd definitely need to store not only the information about the
interface part in the .ppu file, but also the implementation part, so
that any child package can access and use this information.
Because without separate compilation(-units), child packages are
relatively useless. After all the real big advantage is that you can
extend a package without touching the existing one.
The classic example from the Ada95 Rationale, for your convinience
converted into "Pseudo Pascal":
--- 8< ---
unit
ComplexNumbers;
interface
type
Complex; // Incomplete (opaque) type.
// Further specified in implementation part.
operator + (Left, Right: Complex) : Complex;
// similarly "-", "*" and "/"
function CartesianToComplex (Real, Imag : Double) : Complex;
function RealPart (X : Complex) : Double;
function ImagPart (X : Complex) : Double;
implementation
...
end {ComplexNumbers}.
--- 8< ---
Now the only ways to add functionality to the unit would be to
1) make "Complex" a non-opaque type, and add another
unit "ComplexNumbersPolar", or
2) change the original "ComplexNumbers" unit by adding the newly needed
funtionality, thus forcing recompilation or - even worse - possibly
introducing bugs to already tested code.
Approach 1) has the disadvantage that I still can't use internal
subroutines declared in the original "ComplexNumbers" unit.
This usually forces me to add another package which exposes this
formerly private part and declare that this private package *should*
only be used by this, or that, or any extending unit, but not "normal"
user code. As with any such suggestions, they can't be forced to other
developers. ;)
Now, if we had child packages all this could be avoided, we simply add a
subpackage like this:
--- 8< ---
unit
ComplexNumbers.Polar;
interface
function PolarToComplex (R, Theta : Double) : Complex;
function Abs (Right : Complex) : Double;
function Arg (X : Complex) : Double;
implementation
...
// This part now has access to the (opaque) type
// "Complex" just like "ComplexNumbers" has.
// IOW: Like it was declared in here.
end {ComplexNumbers.Polar}.
--- 8< ---
No touching of the original "Complex_Numbers", no recompilation for
units already using it and the knowledge that the original code has not
changed a bit. Additionally the inner working of the type "Complex" is
still not exposed to any other unit.
And yes, I miss that.
Vinzent.
More information about the fpc-pascal
mailing list