[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