comp.lang.ada
 help / color / mirror / Atom feed
From: matthew_heaney@acm.org (Matthew Heaney)
Subject: Re: Mutually dependent private types
Date: 1998/05/22
Date: 1998-05-22T00:00:00+00:00	[thread overview]
Message-ID: <matthew_heaney-ya023680002205981805440001@news.ni.net> (raw)
In-Reply-To: 3565B105.9BFB4788@ac3i.dseg.ti.com


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.

>> This is out-of-the-box Ada 95.  No complex language extensions or
>> Unchecked_Conversion or implementing types using access types is required.
>
>Yes, but unfortunately it forces Ada95 to act a lot like Smalltalk. 

But only because you derive every tagged type from the same root type (a la
Smalltalk).  In that case, you really are throwing _all_ static type checks
out the window.  There is no need for that.  Simply create a different root
type for each hierarchy.

>The
>programmer presumably knows statically that O1 is always supposed to be
>a T1 and O2 is always supposed to be a T2, but this coding style
>prevents the compiler from knowing that.  It is very possible that
>someone could write code that tried to pass something other than a T2
>into P1.Op1. 

If you use different type hierarchies, then the client could only
accidently pass types in the T2 hierarchy.  But this is very unlikely, for
example

package T2_Roots is

   type NO_ONE_DERIVE_FROM_THIS_EXCEPT_P2_T2 is
      abstract tagged null record;

end;

with T2_Roots;
package P2 is

   type T2 is
      new T2_Roots.NO_ONE_DERIVE_FROM_THIS_EXCEPT_P2_T2 with private;
...
end;

Hopefully it will be obvious that package T2_Roots is only for use by P2!

Of course, if, during a code walk-through, you see this

with T2_Roots;
package P3 is

   type T is
      new T2_Roots.NO_ONE_DERIVE_FROM_THIS_EXCEPT_P2_T2 with private;
...
end;

then you have bigger problems than mere language omissions.

>Such code would of course be a bug, but it wouldn't be
>caught until the call to P1.Op1 was actually executed and the tag-check
>was performed.  Depending on the testing scheme used during development,
>this call may or may not get executed.  So this bug could actually go
>undetected during testing and wind up being reported by an irate end
>user.

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
(especially since you could suppress the check, knowing that ONLY P2.T2
derives from T2_Root).

Remember, the chain of mutual dependencies only needs to be broken in one
place.  Adam's problem could have been solved simply as

with T2_Roots;
package P1 is

   type T1 is private;

   subtype T2 is 
      T2_Roots.NO_ONE_DERIVE_FROM_THIS_EXCEPT_P2_T2'Class;

   procedure Op1 (O1 : T1; O2 : T2);
...
end;

with T2_Roots;
with P1;

package P2 is

   type T2 is 
      new T2_Roots.NO_ONE_DERIVE_FROM_THIS_EXCEPT_P2_T2;

   procedure Op2 (O2 : T2; O1 : P1.T1);
...
end;

Only one type (here, T2) needs to be split into a root & derived type pair.

>> I read John's paper, but I don't find his argument convincing.  Doesn't the
>> following code solve the putative with'ing "problem"?
>
>[snip Matt's example]
>
>The *_Rep types aren't even necessary, if you're going to go with the
>universal root type strategy:
>
>package Adam is
>   type Root is abstract tagged null record;
>end Adam;

I argue that this is going too far.  Each type can have it's own root type,
as in

package T1_Roots is
   type T1_Root is abstract tagged null record;
end;

with T1_Roots;
package P1 is
   type T1 is new T1_Roots.T1_Root with private;
...
end;

package T2_Roots is
   type T2_Root is abstract tagged null record;
end;

with T2_Roots;
package P2 is
   type T2 is new T2_Roots.T2_Root with private;
...
end;

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.




  reply	other threads:[~1998-05-22  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
1998-05-21  0:00 ` Matthew Heaney
1998-05-22  0:00   ` John Volan
1998-05-22  0:00     ` Matthew Heaney [this message]
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
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
  -- 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 ` Brian Rogoff
1998-05-22  0:00 ` Matthew Heaney
replies disabled

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