comp.lang.ada
 help / color / mirror / Atom feed
From: bobduff@world.std.com (Robert A Duff)
Subject: Re: Allocating "initialized" limited types...
Date: 1996/08/31
Date: 1996-08-31T00:00:00+00:00	[thread overview]
Message-ID: <Dx0q2E.2Bw@world.std.com> (raw)
In-Reply-To: JSA.96Aug30173704@alexandria


In article <JSA.96Aug30173704@alexandria>,
Jon S Anthony <jsa@alexandria> wrote:
>What was the reasoning behind the 4.8(7) definition that an initialized
>allocator boils down to an assignment?  Any reason why this could not have
>been defined as the creation of an instance with the fields as given by
>the qualified expression?

Well, it *is* a copy, and the whole point of limited types is to prevent
copying.  I don't see any difference between assignment and just copying
all the fields over -- that's what assignment *does*.

For example, suppose there is a limited private type implemented as an
access type.  The designer of that abstraction wanted to prevent having
two such pointers pointing to the same thing, and so made it limited.
Now, a client says:

    X: The_Limited_Type;
    type T is access The_Limited_Type;
    Y: Y := new The_Limited_Type'(X); -- Illegal.

If this were legal, the client would have succeeded in making a copy of
X, which is exactly what "limited" is supposed to prevent.

Imagine a limited record type containing a component with an access
discriminant that points to the outer record.  Allowing a copy would
destroy that access discriminant.

Imagine copying a task -- it makes no sense in Ada 95.  (I suppose it
could have made sense in Ada 83, where a task value was not a task, but
a pointer to a task.  But in Ada 95, a task value is a task -- just like
an integer value is an integer.)

I don't see why allocators are special -- a copy is a copy.

Ada 95 went to some trouble to patch some holes in Ada 83 where one
could make copies of limited types, by the way.

>Because of this, allocating limited types with given fields is not very
>clean and in some cases requires superfluous conversions.  Maybe someone
>knows a clever way out of this?  For example, suppose you have a limited
>tagged type and an access type whose designated type is the tagged type's
>class:
>
>    type T is tagged limited private;
>    type T_Ref is access all T'Class;
>
>Utilizing T_Ref, you construct some general operations constructing
>and manipulating hetergeneous lists of things in T'Class.  At certain
>places you will want to create these lists by adding to them things
>in T'Class provided by allocators of the relevant child types.  So,
>you may have something like:
>
>    type C is new T with private;  -- Extends with new fields...
>...
>    A_List  : Car_Cdr_List_Where_Car_Is_T_Ref;
>    Obj_Ref : T_Ref;
>
>    loop
>        ...
>(1)     Obj_Ref := new C'(....); -- ILLEGAL, assignment to limited type!

It's not clear to me what you plan to put in the "....", since T and C
are both private.

>(2)     A_List := Obj_Ref + A_List;
>        ...
>    end loop
>
>(*) Changing (1) to
>
>        Obj_Ref := new C;
>        Obj_Ref.New_Field1 := ... -- ILLEGAL, No such field in this view!

You can say C(Obj_Ref.all).New_Field1 := ...

Not exactly pretty, but it works.

Another useful trick is to make all the record fields into discriminants
(possibly of access type).  Then you can initialize them using a
discriminant constraint, which does the full coverage check you want.

>Doesn't help and is much more prone to errors (forget one of those fields???)

Maybe you're really asking why limited types don't allow aggregates?
The "don't forget fields" feature is a property of aggregates, not
allocators.  It's not clear how one could deal with access discrims in
an aggregate.

Maybe you could come up with some rules that allow aggregates in some
cases, but only in initial values.  Note that "X: T := expression;" is
analogous to "new T'(expression);" -- both are initializers.  The idea
would be, I suppose, that the aggregate is built "in place", so there's
no copy.  You could also allow function_calls, where the function
returns a local, if you're willing to have that local live outside the
function (i.e. the local "becomes" the new object being initialized).  I
think Henry Baker once published a paper along those lines, but I don't
have a reference (sorry).

>IMO, this sucks, both because it requires a superfluous conversion and
>because of the fact that it still requires error prone field by field
>assignment. ...

I'll grant you that Ada 95 has entirely too many superfluous conversions
between access types.  There are many other cases.  The problem is that
you normally want type-equivalence-by-structure for access types,
whereas Ada always uses (essentially) type-equivalence-by-name.  Access
parameters are helpful, but that only works for parameters.

- Bob




  reply	other threads:[~1996-08-31  0:00 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1996-08-30  0:00 Allocating "initialized" limited types Jon S Anthony
1996-08-31  0:00 ` Robert A Duff [this message]
1996-09-02  0:00   ` Jon S Anthony
1996-09-04  0:00     ` Joel VanLaven
1996-09-05  0:00       ` Robert A Duff
1996-09-06  0:00     ` Jon S Anthony
1996-09-02  0:00   ` Jon S Anthony
1996-09-03  0:00     ` Robert A Duff
1996-09-06  0:00     ` Jon S Anthony
1996-09-04  0:00   ` Jon S Anthony
1996-09-05  0:00     ` Robert A Duff
1996-09-05  0:00   ` Jon S Anthony
1996-09-05  0:00     ` Robert A Duff
replies disabled

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