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/26
Date: 1998-05-26T00:00:00+00:00	[thread overview]
Message-ID: <356B226F.EF05E927@ac3i.dseg.ti.com> (raw)
In-Reply-To: matthew_heaney-ya023680002205981805440001@news.ni.net


Matthew Heaney wrote:
> 
> In article <3565B105.9BFB4788@ac3i.dseg.ti.com>, John Volan
> <johnv@ac3i.dseg.ti.com> wrote:
> 
> >> 3) The mutual dependency in operations is effected by making the other type
> >> have type Root'Class, in the spec.  In the body, just downcast the object
> >> to the representation type.  Of course, the compiler can't verify
> >> statically that the object is really of the required type, but you'll find
> >> out at runtime, because a tag check happens when you downcast.
> >
> >See http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#strong_typing,
> >where I describe how the with-ing problem can be avoided, at the expense
> >of Ada95's static strong typing checks, by deriving all your object
> >classes from some universal root type (Objects.Object_Type was my
> >suggestion).
> 
> Yes, but I don't agree that all tagged types must derive from the _same_
> root type.  Each hierarchy can have a different root type.

Matt, in your original example, you had T1 and T2 (and T1_Rep and
T2_Rep) all derive from a common Root type. That looks a lot like the
idea of having a universal root type that everything derives from.  (My
real objection to your example was that you declared T1_Rep and T2_Rep
in a common *package*, which I thought was unnecessary.)

But if you want to go in the other direction, sure, you could have these
more focused "root" types act as forward declarations for specific
"actual" types.  Norman Cohen originally came up with that idea: Using
inheritance as a mechanism for doing forward type declarations.  

I still have the same objections to that scheme that I had before: IMHO,
Ada95's inheritance was really "intended" to support polymorphic
programming, where your problem domain clearly calls for a common
generalized abstraction implemented by multiple specialized
abstractions. But a forward declaration is the exact *opposite* of
polymorphism: A forward type declaration is supposed to bear a
one-to-one correspondence with a full type declaration.  Simulating a
forward type declaration with a spurious extra level of inheritance
creates a situation where the compiler thinks you want polymorphism, but
you actually don't.  As you point out yourself, this spurious
polymorphism creates an opportunity where someone could try (either
accidentally or maliciously) to provide more than one full type for the
same "forward" type.

Furthermore, what if you're already using inheritance to support true
polymorphism, and then you discover you need to break a mutual
dependency somewhere in your class hierarchy?  You might end up with a
situation I call "inheritance collision": That's where you're trying to
apply Ada's inheritance mechanism for two competing purposes, but you're
faced with the fact that Ada only supports single inheritance.  Sure,
it's possible to wiggle your inheritance hierarchy around so that it'll
work and you can still keep your mutually-dependent types in different
packages. But I find that to be awkward and artificial.

Bottom line, I don't think anyone can legitimately claim that Ada95
offers a solution to mutual dependency problems "right out of the box". 
All you can say is that there are various workarounds, with varying
degrees of awkwardness, that can be used to make up for a fundamental
hole in the language.

[Snip my objection to the loss of strong type checking and the spurious
extra tag check...]

> There are constraint checks for all additions, subtractions, etc.  There
> are index checks for array dereferences.  There are storage checks during
> allocation.  etc.  One extra tag check isn't going to make a difference

I'm not sure you can make an analogy with constraint, index, and storage
checks.  In general, you can't know statically when an arithmetic
operation is going to violate a constraint, or when you're going to run
out of memory, and so on, so all of those dynamic checks are necessary. 
But you can certainly know statically what strong types you're expecting
in your variables and subprogram parameters.  Type-checking should only
become a dynamic thing when you deliberately set up an inheritance
hierarchy and do polymorphic class-wide programming. But a simple case
of mutual dependency shouldn't call for polymorphism.

> Furthermore, this split is only required when there's mutual dependency.
> Most types are definately not mutually dependent, and so this workaround
> should only seldom be necessary.

Depends on the style of software design you're using, which depends a
lot on your programming culture.  Java, for instance, doesn't place any
impediments on mutual dependencies, so there are several cases of mutual
dependencies already in the standard Java API.  My understanding is that
this has caused problems for folks trying to use Ada95 as a front-end
language for the Java Virtual Machine.  I haven't done much with
Ada95-to-JVM compilers (like AdaMagic), so I don't know what solutions
they've come up with for that. Maybe Tucker can comment...

-- 
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. :-)" );




  parent reply	other threads:[~1998-05-26  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 ` Matthew Heaney
1998-05-22  0:00   ` John Volan
1998-05-22  0:00     ` Matthew Heaney
1998-05-26  0:00       ` Robert I. Eachus
1998-05-26  0:00         ` John Volan
1998-05-27  0:00           ` Robert I. Eachus
1998-05-29  0:00             ` John Volan
1998-05-27  0:00           ` Jerry van Dijk
1998-05-29  0:00             ` John Volan
1998-05-26  0:00       ` John Volan [this message]
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-21  0:00 ` John Volan
  -- strict thread matches above, loose matches on Subject: below --
1998-05-22  0:00 adam
1998-05-22  0:00 ` John Volan
1998-05-22  0:00 ` Matthew Heaney
1998-05-22  0:00 ` Brian Rogoff
replies disabled

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