comp.lang.ada
 help / color / mirror / Atom feed
* Re: New Tree Example (was Re: MI - clutchin
@ 1992-10-02 15:50 Peter Klein
  0 siblings, 0 replies; 2+ messages in thread
From: Peter Klein @ 1992-10-02 15:50 UTC (permalink / raw)


In article 92Sep18160904@Dr_No.mitre.org, eachus@Dr_No.mitre.org (Robert I. Eac
hus) writes:
>
>    Gee, this is getting complex.  I'm going to try to break it into
>separate threads.  (I'll be in Pittsburgh most of next week, so
>silence will not construe consent to anything. :-)
>

I hope you don't mind if I answer this thread first. I'm pretty short of time
at the moment, and I think the more fundamental things can be discussed better
with this simple example.

>In article <1992Sep15.140840.3405@Urmel.Informatik.RWTH-Aachen.DE> pk@rwthi3.i
nformatik.rwth-aachen.de (Peter Klein) writes:
>
>   Sorry, but I still don't see how you handle polymorphism with generics.
>   One last example on this: Suppose you have some container class, let's
>   say a list. In this list, you want to store objects of different types.
>   In the implementation of the list, you don't know what types, you don't
>   even know how many. In fact, you *shouldn't* know this, because it has
>   nothing to do with the list itself. Now, please, how do you do this with
>   generics?
>
>   I'll answer the last question first...
>
>   package Mixed_Lists is
>
>      type List is private;
>
>      function Is_Empty(L: List) return Boolean;
>      function New_List...
>      -- all the usual operations which don't mention elements.
>
>      generic
>        type Item is private;
>      package New_Elements is
>        procedure Append(L: in out List; E: in Item);
>        ...
>      end New_Elements;
>
>   private
>     ...
>   end Mixed_Lists;
>
>  -- You can do all this with just a little attention to magic in
>  -- Ada 83.  (Each instance of New_Elements gets a unique tag
>  -- from Mixed_Lists, and does run-time type checking when
                                 ^^^^^^^^^^^^^^^^^^^^^^
>  -- removing things from lists by matching tags.  Of course, in
>  -- Ada 9X you can use tagged types to do that automatically.)
>
Well, this is exactly what's wrong with your example. You loose the
ability to treat all elements in the list in a uniform way: Using
generics, it is the *client* of the list package who determines how
to do certain things with the elements - depending on their actual
type. In the polymorphistic approach, the elements *themselves* carry
the information about how to do something with them.
Think about all the clients of such a list who don't care about the
actual type of a given element - they simply demand that a certain
method can be applied to all elements in the list.
Let's say we have a list client which wants to print the list. It
knows that all elements can be printed, but it doesn't care how this
is done for the element types in question.
Now this is exactly what polymorphism buys you: You can apply a method
to an object, and the *object* knows what to do. In your proposal, the
*client* always has to know which instantiation he has to use to perform
the right action.
One important point here: We are talking about *single inheritance* so far.

>    Having said all that, this is the wrong way round, especially in
>Ada 9X.  First create the node type, which may just be a placeholder,
>then mix in the lists, then derive the various element types from the
>node type:
>
>     type Node_Type is tagged record null; end record;
>
>     generic
>       type Element is tagged private;
>     package Lists is
>       type Item is new Element with null; -- (I don't like the syntax either.
)
>       type List is private;
>       -- define list operations here. (But make sure they are class wide.)
>     private
>       ...
>     end Lists;
>
>     package Node_Lists is new Lists(Node_Type);
>    
>     package Identifiers is
>       type Identifier_Node is new Node_Lists.Item with private;
>       -- operations on identifiers go here.
>     private
>       ...
>     end Identifiers;
> 
>     -- etc., etc.
>
Excuse me here; my knowledge of Ada 9X syntax doesn't suffice to understand
this example.

>  So far so good, but now we can go one step further.  Since
>the abstraction of mixed lists is a generally useful one, and there is
>no particular need for the parent list element type to have any
>attibutes other than those associated with lists, there is no
>particular reason to make the list package a generic, and in fact
>there is no reason to use multiple inheritance either. :-)

:) Don't think so. Actually, if I follow your advice to keep the attribute
of 'listable element' apart from other attributes of the element, this is
exactly the place where multiple inheritance comes back into the game again.
In this case, I make up a virtual base class listable_element, which defines
the 'shape' of an element which can be put into the list. Since this feature
of being listable has got nothing to do with other properties of an element,
it has to be assumed that some possible list element type also is in some
arbitrary class hierarchy. Now, if I want to put elements of an arbitrary
type (possibly a subtype of an arbitrary supertype) into my list, I'll make
this type a subtype of listable_element also. Which, in general, implies
that it inherits from at least two supertypes.

Peter
---
Peter Klein                        E-Mail: pk@rwthi3.informatik.rwth-aachen.de
Lehrstuhl fuer Informatik III      Tel.: +49/241/80-21320
Ahornstrasse 55                    Fax.: +49/241/80-21329
RWTH Aachen
D-5100 Aachen
Germany

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

* Re: New Tree Example (was Re: MI - clutchin
@ 1992-10-03  2:35 Robert I. Eachus
  0 siblings, 0 replies; 2+ messages in thread
From: Robert I. Eachus @ 1992-10-03  2:35 UTC (permalink / raw)


   Okay, once more into the fray, but based on some of Peter's
comments this is getting to the point of diminishing returns for now.
(Not a criticism of Peter, but we are at the edge of the current state
of definition of Ada 9X.  Before I say more about how you should
program in Ada 9X, the language needs to be closer to frozen.)

In article <1992Oct2.155045.18473@Urmel.Informatik.RWTH-Aachen.DE>
pk@rwthi3.informatik.rwth-aachen.de (Peter Klein) writes:

   In article 92Sep18160904@Dr_No.mitre.org, eachus@Dr_No.mitre.org
(Robert I. Eachus) writes:

   >> -- You can do all this with just a little attention to magic in
   >> -- Ada 83.  (Each instance of New_Elements gets a unique tag
   >> -- from Mixed_Lists, and does run-time type checking when
   >				 ^^^^^^^^^^^^^^^^^^^^^^
   > -- removing things from lists by matching tags.  Of course, in
   > -- Ada 9X you can use tagged types to do that automatically.)

   > Well, this is exactly what's wrong with your example. You loose
the
   > ability to treat all elements in the list in a uniform way: Using
   > generics, it is the *client* of the list package who determines
how
   > to do certain things with the elements...

   > One important point here: We are talking about *single
   > inheritance* so far.

   I don't understand what you are criticizing.  Of course it is
single inheritance, and of course it is unnecessarily difficuly in Ada
83.  But what I was pointing out was that, while single inheritance is
natural in Ada 9X, it is not impossible in Ada 83.  (Just painful in
some cases.)

   >> Having said all that, this is the wrong way round, especially in
   >> Ada 9X.  First create the node type, which may just be a
placeholder,
   >> then mix in the lists, then derive the various element types
from the
   >> node type:
   >>
   >> type Node_Type is tagged record null; end record;
   >>
   >> generic
   >> type Element is tagged private;
   >> package Lists is
   >> type Item is new Element with null; -- (I don't like the syntax
either.)
   >> type List is private;
   >> -- define list operations here. (But make sure they are class
wide.)
   >> private
   >> ...
   >> end Lists;
   >>
   >> package Node_Lists is new Lists(Node_Type);
   >>
   >> package Identifiers is
   >> type Identifier_Node is new Node_Lists.Item with private;
   >> -- operations on identifiers go here.
   >> private
   >> ...
   >> end Identifiers;
   >>
   >> -- etc., etc.
   >>

   > Excuse me here; my knowledge of Ada 9X syntax doesn't suffice to
   > understand this example.

    It corresponds to creating a list class in say, Smalltalk, and
deriving from it.  However there is a very subtle but important
difference, you actually don't inherit from the list class, but from
the "element of list" class.  The list type is not an extensible type,
but it is possible to make lists of all types derived from
Node_Lists.Item. In effect the adding of the list operations involves
inheritance from the element type with a mixin of list attributes.
However, there is a single list type.  Deriving from Node_Lists.Item
creates a new class, but all the list operations still operate on the
single list type.  (You could derive from Node_Type and instantiate
Lists again if you wanted the two types to have different list types.)
So this is a form of multiple inheritance, but a fairly safe one.

  > :) Don't think so. Actually, if I follow your advice to keep the
  > attribute of 'listable element' apart from other attributes of the
  > element, this is exactly the place where multiple inheritance
  > comes back into the game again.  In this case, I make up a virtual
  > base class listable_element, which defines the 'shape' of an
  > element which can be put into the list. Since this feature of
  > being listable has got nothing to do with other properties of an
  > element, it has to be assumed that some possible list element type
  > also is in some arbitrary class hierarchy. Now, if I want to put
  > elements of an arbitrary type (possibly a subtype of an arbitrary
  > supertype) into my list, I'll make this type a subtype of
  > listable_element also. Which, in general, implies that it inherits
  > from at least two supertypes.

    I had to play with this awhile until I understood the percieved
problem.  The misunderstanding is that in Ada you can sort of derive
through a class to add operations, so if you want to add many
attributes you can have many ancestors instead of many parents.  Let's
say that above you are talking about two parent classes LISTABLE and
ARBITRARY, and a (single) child of both (Single for artistic
simplicity, I'm not going to try to draw the multiple child case):

               LISTABLE	    ARBITRARY
		      \       /
		       \     /
                        \   /
                        CHILD

    In Ada you get something more like:

                      ARBITRARY			 LISTS
                          |			   |
			  |
                          |			   |
                          |
                          |			   |
                      LISTABLE_CHILD- - - - -LISTS_OF_CHILDREN

    The instantiation which creates both LISTABLE_CHILD and
LISTS_OF_CHILDREN looks like a mixin, but notice that it actually
creates two types, and operations (such as APPEND) which are
operations of both types.  (I dotted the relationship between LISTS
and LISTS_OF_CHILDREN because it is really a template-instance
relationship rather than parent child.  LISTABLE_CHILD however is a
true child of ARBITRARY.)


--

					Robert I. Eachus

with STANDARD_DISCLAIMER;
use  STANDARD_DISCLAIMER;
function MESSAGE (TEXT: in CLEVER_IDEAS) return BETTER_IDEAS is...

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

end of thread, other threads:[~1992-10-03  2:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1992-10-02 15:50 New Tree Example (was Re: MI - clutchin Peter Klein
  -- strict thread matches above, loose matches on Subject: below --
1992-10-03  2:35 Robert I. Eachus

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