comp.lang.ada
 help / color / mirror / Atom feed
* Re: Membership tests for tagged types
@ 1993-06-26 14:50 howland.reston.ans.net!noc.near.net!inmet!spock!stt
  0 siblings, 0 replies; 2+ messages in thread
From: howland.reston.ans.net!noc.near.net!inmet!spock!stt @ 1993-06-26 14:50 UTC (permalink / raw)


In article <20csgf$5tr@huon.itd.adelaide.edu.au> 
  andrewd@achilles.cs.adelaide.edu.au (,2285592, Andrew Dunstan) writes:

>As a follow-up on my request for info on access discriminants, I'd 
>really appreciate some simple info (fairly urgently) on membership
>tests for tagged types and classes.
>
>For instance, can one say (for X of some class-wide type) something like:
>
>case X'tag is
>  when A'class => ...
>  when B'class => ...
>  when others => ...
>end case;
>
>?

No.  In a very early version of the 9X proposals, we included
a "polymorphic" case statement.  However, it was somewhat
complex, and the general feeling was that a general OO principle
is that "case statements are harmful."  Nevertheless, we have
preserved a simple membership test that can be used to test
whether the value of an object is in a particular class.
A chained if/then/elsif/elsif can be used to simulate the
effect of the case statement if you don't give a hooey about 
someone else's notion of what is or what is not O-O ;-).

If I understand your example, it would be written as follows:

   if X in A'Class then ...
   elsif X in B'Class then ...
   else ...
   end if;

Admittedly not as readable as a "case" statement, but
it gets the job done and it keeps the language itself simpler.

>thanks in advance!

You are welcome.  

As far as access discriminants, I don't have time 
at this moment to provide an elaborate example, but
there is a small example in the Ada 9X Mapping Rationale 
version 4.1 (March 1992, available on ajpo.sei.cmu.edu in 
public/ada9x/ada9x.reports/map-rat-Mar92.9x), that goes 
roughly as follows (the Iterate procedure in the rationale example
seems slightly amiss as I reread it at this moment):

    type Set is limited private;
      -- Abstract "Set" of Item_Type type
    procedure Add_Item(To : in out Set; Item : Item_Type);
    . . .

    type Set_Iterator(Over : access Set) is limited private;
      -- Iterator over a given set, designated by the access discrim
    procedure Start(Iterator : in out Set_Iterator);
      -- (Re)Start iteration at "beginning" of set identified 
      -- by Iterator.Over
    function More(Iterator : Set_Iterator) return Boolean;
      -- return True if more items left in iteration.
    procedure Get_Next(Iterator : in out Set_Iterator;
                       Item : out Item_Type);
      -- Get next item in the iteration.

Here is a typical use:

    S : aliased Set;  -- declare the set ("aliased" so can be
                      -- designated by access discriminant)
  ...
    Add_Item(S, I1);  -- add some items to it
    Add_Item(S, I2);
  ...

    Iter : Set_Iterator(S'Access);  -- declare an iterator over the set
    Item : Item_Type;
  ...
    Start(Iter);   -- start iteration over the set
    while More(Iter) loop
       Get_Next(Iter, Item);  --
       ...  -- do something useful with the item
    end loop;
    
                      
There is probably no real need for the "Start" operation,
presuming that the default initialization of a Set_Iterator
sets it to the "beginning" of the set.  "Start" would be
useful for re-iterating without having to declare a new
Set_Iterator.  So perhaps it might better be called "Restart"
or "Reset."

Note that there are many other uses for access discriminants.
One important use is when one wants to have two or more linked
lists that go "through" the same data structure.  Access discriminants
can be used to allow each component that is a "Link_Type" to
refer to its enclosing data structure.

Also, access discriminants can be used to create type composition 
hierarchies that involve multiple inheritance.  Access discriminants
allow the components that are of the various parent types to gain 
access to the other components of the enclosing object, so they
may interact with one another as necessary.

>andrew
>#  Andrew Dunstan                   #   There's nothing good or bad   #
>#  net:                             #                                 #
>#    adunstan@steptoe.adl.csa.oz.au #   but thinking makes it so.     #
>#  or: andrewd@cs.adelaide.edu.au   #                                 #

S. Tucker Taft     stt@inmet.com
Ada 9X Mapping/Revision Team
Intermetrics, Inc.
Cambridge, MA  02138

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Membership tests for tagged types
@ 1993-06-28  8:47 cis.ohio-state.edu!pacific.mps.ohio-state.edu!math.ohio-state.edu!howland
  0 siblings, 0 replies; 2+ messages in thread
From: cis.ohio-state.edu!pacific.mps.ohio-state.edu!math.ohio-state.edu!howland @ 1993-06-28  8:47 UTC (permalink / raw)


In article <mcook.741125871@fendahl.dev.cdx.mot.com>, mcook@fendahl.dev.cdx.mot
.com (Michael Cook) writes:
: stt@spock.camb.inmet.com (Tucker Taft) writes:
: 
: [...]
: >the general feeling was that a general OO principle
: >is that "case statements are harmful."
: 
: Hmm.  What's wrong with case statements?

There is nothing wrong with case statements from the OO point of view.
Where OO purists have a problem is when you use a discriminant record
and then implement the operations with case statements on the
discriminant.  This is more cleanly implemented through inheritance and
dispatching which makes the code clearer and more maintainable.
However, in Ada 83 we don't have full support for inheritance and no
support for dispatching so we are stuck with case statements and
discriminant records for the time being.

: 
: [...]
: >If I understand your example, it would be written as follows:
: 
: >   if X in A'Class then ...
: >   elsif X in B'Class then ...
: >   else ...
: >   end if;
: 
: >Admittedly not as readable as a "case" statement, but
: >it gets the job done and it keeps the language itself simpler.

I don't think there is really enough information in this example to be
really meaningful. It could be a case where one shouldn't even be using
the class attribute and operator overloading would handle everything
just fine. Or it could be better solved with inheritance and
dispatching.

Here is a case that might be interesting.

Given the type hierarchy

             Dog
              |
     ____________________
     |        |          |
                 
Big_Dog  Medium_Dog Little_Dog

and a stack of Dog'Class objects (a heterogenous stack of Big, Medium and
Little Dogs)

Suppose we want to sort the stack into three homogeneous stacks.

could we just write three insert procedures

   procedure Insert( The_Dog : Big_Dog);
   procedure Insert( The_Dog : Medium_Dog);
   procedure Insert( The_Dog : Little_Dog);
 
one for each stack and then write some sort of loop around
 
   Insert( The_Dog => Pop( The_Stack => Mixed_Dog_List ));
   
where Pop returns the Dog'Class object off the top of the stack?  Here
I would be hoping that the compiler could determine which insert to
call at runtime based on the type of the Dog'Class object.  However
Insert is not a primitive operation of the type Dog so I'm not at all
sure if this is possible.  The alternative would be either a case or
sequence of if statements along with membership tests or restructuring
the code to make Insert a primitive of Dog.

Robb

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~1993-06-28  8:47 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1993-06-26 14:50 Membership tests for tagged types howland.reston.ans.net!noc.near.net!inmet!spock!stt
  -- strict thread matches above, loose matches on Subject: below --
1993-06-28  8:47 cis.ohio-state.edu!pacific.mps.ohio-state.edu!math.ohio-state.edu!howland

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