At 04:14 PM 8/20/98 -0500, Corey Minyard wrote:

>However, after using Java for a while and doing work in object-based
>fault-tolerance, I find that it is quite convenient to have all
>classes in the system derive from one base class.  That way containers
>of more general objects can be built, all objects can be treated the
>same at certain levels, etc.  Also, making handling general interfaces
>(like Java, a special form of multiple inheritance) more general to be
>useful, too.  So the expectation is the user would derive from
>Baseclass.Object, too, for their tagged types.

    Ah, hah!  The old, if all you have is a hammer, everything looks like a
nail problem. ;-)

    Seriously, in Ada you have a lot of models to choose from.In this
particular case, your approach gets bitten by the special status of limited
and controlled types in Ada.  If you need for your container class to
derive from Controlled, you can force that easily.  But if you want only
some of your container subclasses to be controlled, the "Ada way" seems to
be to make the base class uncontrolled, and add controlled components
later.  I generally prefer to let the user define the base type and define
mixins.  That way the user of the package determines if the base type needs
to be limited or controlled.

>I wanted to push generality as far down the package hierarchy as I
>could.  So, for instance, you can take any container and search it,
>get values from it, etc.  Without the genericity pushed all the way
>down the package hierarchy, that was not possible except for a very
>limited set of operations.  Making things as general as possible as
>far down the package hierarchy as possible allows the most allows the
>most flexibility for replacing containers, too.

    I would put the concrete type in the root asgc package.  Some
operations common to all classes could be defined there (as abstract if
necessary).  But any operations that needed to be defined on all subclasses
but had a parameter of the contained type would need to be declared in each
generic leaf.
Doing this would mean that those operations would not dispatch at run time
against all containers, but would have all the nice relationships at
compile time.  Again this comes down to a preference.  I'd get rid of the
two "extra" levels of generic instantiations, but it would eliminate the
possibility of dispatching across container types at run-time.  (Of course,
my opinion is that dispatching between lists and queues is of dubious
utility.)

>If for instance, I am using a fixed doubly linked list and later on I
>determine that I need a dynamic list, or that I need to use an
>array-based list (AList), etc. I can instantiate the variable with a
>different package in one place (if the variable is as generic as
>possible) and the job is done.

    I think that we are both advocating a style where changes at one point
in the code should be all that is necessary to change the container type.
Currently your approach sometimes requires two generic instantiations to be
changed, where I would always change one instantiation, and one type
derivation:

    package My_Queue is new Asgc.Ordered.AList.Fixed(My_Component_Type);
    type Local_Queue is new Asgc.Ordered.AList.Fixed.List_Type;

becomes:

    package My_Queue is new Asgc.Ordered.DList.Expandable(My_Component_Type);
    type Local_Queue is new Asgc.Ordered.DList.Expandable.List_Type;

or whatever.

>The main disadvantage I have seen so far is that lots of package
>instantiation has to be done.  It's kind of a pain, but I don't think
>it contributes much to executable bloat because all but the "leaf"
>packages tend to be very abstract and quite small.

   Yeah, the "code bloat" should all be in the source code.  But I'd like
to elminate some of that--if it can be done without cutting useful features.

>   Then you would say something like:
>
>  package Integer_Base is new Asgc(Contained_Type => Integer);
>  package Integer_Queue is new Integer_Base.Ordered;
>  package Integer_Queue_DList is new Integer_Queue.DList;
>  package Integer_Dynamic_Queue_DList is new Integer_Queue_Dlist.Fixed;
>
>Then later on, instantiate it with:
>
>  My_Queue : Integer_Queue.Object_Class
>               := new Integer_Dynamic_Queue_Dlist.Object;
>
>Then I would use the methods defined in Integer_Queue to operate on
>the queue.
>
>If it was done the way you suggest, you would end up saying:

   Let me provide my version:

   package Integer_List is new Asgc.Ordered.DList.Fixed(Integer);
   My_Queue : Integer_List.List_Ptr := new Integer_List.List;

Although I would really prefere to end up doing:

   package Integer_List is new Asgc.Ordered.DList.Fixed(Integer);
   type Queue is new Integer_List.List;

   My_Queue: Queue := New_Container;



                                        Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...