comp.lang.ada
 help / color / mirror / Atom feed
From: John Volan <johnv@ac3i.dseg.ti.com>
Subject: Re: Mutually dependent private types
Date: 1998/05/21
Date: 1998-05-21T00:00:00+00:00	[thread overview]
Message-ID: <3564C4CD.37DCF114@ac3i.dseg.ti.com> (raw)
In-Reply-To: 6k25ra$6j7$1@nnrp1.dejanews.com


adam@irvine.com wrote:
> 
> I've run into another problem trying to get something implemented in
> Ada 95.  This problem seems superficially similar to John Volan's
> with-ing problem, but I don't think it's quite the same.

Goodness, please don't refer to it as "John Volan's" with-ing problem
... I really don't want to lay claim to the problem itself, all I did
was analyze it to death (see my FAQ web page at
http://bluemarble.net/~jvolan/WithingProblem/FAQ.html).  I suppose in
medical circles they tend to name a disease after the first person to
discover and characterize it, but I'm pretty sure my write-up wasn't the
first time the with-ing problem (syndrome? :-) was discovered or
described ... although it is no doubt the most *exhaustive* description
to date ... :-)

> (1) If I want to have two private types in two separate packages whose
>     *implementations* are mutually dependent on each other, this is
>     easy to do, if we're willing to make the private types accesses:
>
>         package P1 is
>             type T1 is private;
>         private
>             type T1_Info;
>             type T1 is access T1_Info;
>         end P1;
> 
>         package P2 is
>             type T2 is private;
>         private
>             type T2_Info;
>             type T2 is access T2_Info;
>         end P2;
> 
>     and this will work since it's legal for P1's package body to
>     depend on P2 and P2's package body to depend on P1.  The
>     definitions of P1.T1_Info and P2.T2_Info would contain references
>     to the other package's type.

See http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#interfaces,
where I describe how the with-ing problem can be avoided if you can
defer the mutual dependencies until the package bodies.

> (2) Another mutual-dependency situation is this: Suppose I want to
>     have two types T1 and T2 in two different packages, and I want to
>     provide operations on T1 that take T2 as a parameter, and
>     operations on T2 that take T1 as a parameter.  You can't do this
>     by declaring T1 and T1's operations in the same package and do the
>     same for T2, since then the two package specs would have to be
>     mutually dependent.  

Seems to me this isn't just superfically similar to the with-ing
problem, it's exactly the with-ing problem!

>     However, you can solve this problem by
>     separating the type definition from the operations in two separate
>     packages (preferably using child units):
> 
>         package P1 is
>             type T1 is ...
>         end P1;
> 
>         package P2 is
>             type T2 is ...
>         end P2;
> 
>         with P2;
>         package P1.Operations is
>             procedure Some_Operation (X : T1;  Y : P2.T2);
>         end P1.Operations;
> 
>         with P1;
>         package P2.Operations is
>             procedure Some_Operation (X : T2;  Y : P1.T1);
>         end P2.Operations;
> 
>     Actually, you don't have to do this for both packages; you can
>     solve the problem by splitting the operations in just one of the
>     packages.

See http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#primitive,
where I describe how you can avoid the with-ing problem if you don't
need the mutually-dependent operations to be "primitives" for their
respective object types (i.e., if they don't need to be declared in the
same package specs with their types).  But if you *do* need them to be
primitives (i.e., your two types are the roots of two inheritance
hierarchies and you want to do dynamic dispatching to different
implementations of the mutually dependent operations) -- well,
unfortunately, you're stuck in that case.

> (3) But what happens if you want to do both (1) and (2)?  Now the
>     whole thing seems to break down.  If you try to do both of the
>     above, something like:
> 
>         package P1 is
>             type T1 is private;
>         private
>             type T1_Info;
>             type T1 is access T1_Info;
>         end P1;
> 
>         with P2;
>         package P1.Operations is
>             procedure Some_Operation (X : T1;  Y : P2.T2);
>         end P1.Operations;
> 
>     you can't, because the body of Some_Operation cannot do anything
>     useful with X, since the definition of T1_Info is not visible to
>     it.

Why hide the full implementation of T1_Info in the body of P1?  Why not
just declare it in the private part, since you want that declaration to
be available to a child package anyway?

> I've been trying to come up with some way around this problem; for
> example, I thought about putting some routines in the private part of
> P1 that P1.Operations could access to give it information about
> T1_Info, or by setting up another private child package to declare
> actual type info, but I couldn't quite get anything to work.  Does
> anyone know of a good way to accomplish this, without using
> Unchecked_Conversion?  (It's pretty easy to come up with a solution
> using Unchecked_Conversion.)  I might be missing something obvious
> here due to my incomplete knowledge of Ada 95.

Well, I'm not exactly sure what you're trying to do, but it's
interesting that you're using access types to implement your private
types. That implies that you don't have a problem dealing with
"reference semantics" (i.e., if X1 and X2 are variables of type T1, and
X1 = X2, then X1 and X2 aren't just referring to two T1_Info objects
that contain similar values, they're both referring to the *same*
T1_Info object).  Sounds like you might be groping for a way to create
some sort of deferred reference type that can stand in the place of an
object type (so you can declare the specs of mutually-dependent
operations) and then later "bind" that reference type to that object
type (when you're ready to implement the operation bodies).  All
solutions to the with-ing problem (even Tucker's "with type" proposal)
pretty much amount to this sort of "deferred binding".
  
You might want to try using my generic Forward package (see my FAQ) to
set yourself up with the reference types you need. Yes, it does use
Unchecked_Conversion underneath the covers, but it guarantees
type-safety despite that.  If you're uncomfortable with the
Unchecked_Conversions, I've also sketched out an alternative
implementation of Forward that avoids them, at the expense of tying all
your object types into a common inheritance hierarchy.

Hope that helps.

P.S. Of course, there's always the "outside-the-box" solution: Program
in a language that's immune to this sort of syndrome ... ;-)

-- 
Signature volanSignature = 
  new Signature
  ( /*name:      */ "John G. Volan",
    /*employer:  */ "Raytheon Advanced C3I Systems, San Jose",
    /*workEmail: */ "johnv@ac3i.dseg.ti.com",
    /*homeEmail: */ "johnvolan@sprintmail.com",
    /*selfPlug:  */ "Sun Certified Java Programmer",
    /*twoCents:  */ "Java would be even cooler with Ada95's " +
                    "generics, enumerated types, function types, " +
                    "named parameter passing, etc...",
    /*disclaimer:*/ "These views not packaged in COM.ti.dseg.ac3i, " +
                    "so loading them throws DontQuoteMeError. :-)" );




  reply	other threads:[~1998-05-21  0:00 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1998-05-21  0:00 Mutually dependent private types adam
1998-05-21  0:00 ` John Volan [this message]
1998-05-21  0:00 ` Matthew Heaney
1998-05-22  0:00   ` John Volan
1998-05-22  0:00     ` Matthew Heaney
1998-05-26  0:00       ` John Volan
1998-05-26  0:00         ` Matthew Heaney
1998-05-27  0:00           ` John Volan
1998-05-27  0:00             ` Matthew Heaney
1998-05-28  0:00               ` John Volan
1998-05-28  0:00                 ` Matthew Heaney
1998-05-29  0:00                   ` John Volan
1998-05-29  0:00                 ` Brian Rogoff
1998-05-29  0:00                   ` John Volan
1998-05-29  0:00                     ` Brian Rogoff
1998-05-29  0:00                       ` John Volan
1998-05-30  0:00                 ` Geoff Bull
1998-05-30  0:00                   ` Fergus Henderson
1998-06-01  0:00                     ` John Volan
1998-06-02  0:00                       ` Fergus Henderson
1998-06-04  0:00                       ` Robert Dewar
1998-05-26  0:00       ` Robert I. Eachus
1998-05-26  0:00         ` John Volan
1998-05-27  0:00           ` Jerry van Dijk
1998-05-29  0:00             ` John Volan
1998-05-27  0:00           ` Robert I. Eachus
1998-05-29  0:00             ` John Volan
  -- strict thread matches above, loose matches on Subject: below --
1998-05-22  0:00 adam
1998-05-22  0:00 ` Brian Rogoff
1998-05-22  0:00 ` Matthew Heaney
1998-05-22  0:00 ` John Volan
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox