comp.lang.ada
 help / color / mirror / Atom feed
* Suggestion: Allow functions returning abstract types in certain situations
@ 2014-05-21 14:52 Victor Porton
  2014-05-21 16:10 ` Adam Beneschan
  0 siblings, 1 reply; 13+ messages in thread
From: Victor Porton @ 2014-05-21 14:52 UTC (permalink / raw)


I think the standard should allow functions returning abstract types, but we 
can restrict to call such functions ONLY in parent parts of record 
extensions or private extensions.

Otherwise, I see no way to create aggregates derived of abstract private 
types.

-- 
Victor Porton - http://portonvictor.org

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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-21 14:52 Suggestion: Allow functions returning abstract types in certain situations Victor Porton
@ 2014-05-21 16:10 ` Adam Beneschan
  2014-05-21 19:09   ` Dan'l Miller
  2014-05-21 22:04   ` Robert A Duff
  0 siblings, 2 replies; 13+ messages in thread
From: Adam Beneschan @ 2014-05-21 16:10 UTC (permalink / raw)


On Wednesday, May 21, 2014 7:52:27 AM UTC-7, Victor Porton wrote:
> I think the standard should allow functions returning abstract types, but we 
> can restrict to call such functions ONLY in parent parts of record 
> extensions or private extensions.

Unless you mean "extension aggregates", I'm not sure what you're referring to.  An extension aggregate is an aggregate where the parent part is specified as an expression and the extension fields follow the "with" keyword.  So are you referring to something like this?

    package Pack1 is
        type T1 is abstract tagged record ... end record;
        function Func (X : Integer) return T1;  -- not currently legal
        ...

    package Pack2 is
        type T2 is new Pack1.T1 with record 
            New_Data : Integer;
            ...

    Rec : T2 := (Pack1.Func(N) with New_Data => 0, ...);

If that isn't what you mean by "parent parts of record extensions or private extensions", please explain what you mean, preferably with some sample code. 

Although at first glance this appeared reasonable to me, I think there's a huge problem: how would you write the *body* of the function?  The function would have to return something.  The language doesn't allow you to declare objects of an abstract type, so Func could not declare a local variable "Result" of type T1 that it could return.  Nor could it return an aggregate, which involves creating a temporary object.  In my view, the language model depends heavily on the assumption that an object can never be created whose tag refers to an abstract type; allowing the rule to *ever* be relaxed could be disastrous.

For extension aggregates, perhaps an alternative would be to allow a *procedure* with an OUT parameter as the parent part of an extension aggregate?  Something like

    package Pack1 is
        type T1 is abstract tagged record ... end record;
        procedure Setup (Obj : out T1; X : Integer);  -- not currently legal

and then

    Rec : T2 := (Pack1.Setup(**THIS**, N) with New_Data => 0, ...);

This wouldn't require creating an object of type T1 at any point.  In effect, the program would create an object Temp of type T2, use T1(Temp) [view conversion] as a parameter to Setup which presumably would initialize some fields declared in T1, then initialize the extension fields.  [Note that T1(Temp) does not create an object whose tag is the tag of T1; the object's run-time type is still T2, but the program is now working with a *view* of that object that only allows the fields declared for T1 to be visible.]  The tricky part would be coming up with a syntax; perhaps the "use" keyword could be given a new job?

    Rec : T2 := (use Pack1.Setup(T2, N) with New_Data => 0, ...);

Here I used "use" to indicate that we're going to use a procedure to help set up the fields, rather than using an expression.  (Or maybe "procedure" instead of "use" would work too?)  As for how to specify the "temporary object" that would be passed as a parameter, I used the type name.  Some details would have to be worked out, such as whether and when Initialize would be called if T2 is controlled, build-in-place semantics, and what happens if there are discriminants involved.

                                 -- Adam

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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-21 16:10 ` Adam Beneschan
@ 2014-05-21 19:09   ` Dan'l Miller
  2014-05-21 22:09     ` Robert A Duff
  2014-05-21 22:04   ` Robert A Duff
  1 sibling, 1 reply; 13+ messages in thread
From: Dan'l Miller @ 2014-05-21 19:09 UTC (permalink / raw)


On Wednesday, May 21, 2014 11:10:44 AM UTC-5, Adam Beneschan wrote:
> On Wednesday, May 21, 2014 7:52:27 AM UTC-7, Victor Porton wrote:
> 
> > I think the standard should allow functions returning abstract types,

The size of an abstract type is not known in this situation.  Perhaps you should reconsider your design (and your critique of Ada) to focus on functions returning some variety of *access* to abstract type  or abstract type 'Class (rather than returning an instance of an abstract type's eventual concrete type).

> > but we 
> > can restrict to call such functions ONLY in parent parts of record 
> > extensions or private extensions.

In C++ this is called slicing, which is undefined behavior and which is considered one of the ways to drive off the cliff in C++.  Ada should absolutely not permit any form of slicing.

> Unless you mean "extension aggregates", I'm not sure what you're referring to.  An extension aggregate is an aggregate where the parent part is specified as an expression and the extension fields follow the "with" keyword.  So are you referring to something like this?
> 
> 
> 
>     package Pack1 is
>         type T1 is abstract tagged record ... end record;
>         function Func (X : Integer) return T1;  -- not currently legal

This whole topic seems to be going nowhere fast.  The size of T1's eventual concrete type (i.e., some member of T1'Class) cannot be known by Func (nor in general by callers of Func).  There could be many such eventual concrete types of T1; hence the insurmountable question will always be:  which member of T1'Class was instantiated concretely?

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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-21 16:10 ` Adam Beneschan
  2014-05-21 19:09   ` Dan'l Miller
@ 2014-05-21 22:04   ` Robert A Duff
  2014-05-21 22:33     ` Adam Beneschan
  1 sibling, 1 reply; 13+ messages in thread
From: Robert A Duff @ 2014-05-21 22:04 UTC (permalink / raw)


Adam Beneschan <adambeneschan@gmail.com> writes:

> Although at first glance this appeared reasonable to me, I think
> there's a huge problem: how would you write the *body* of the
> function?  The function would have to return something.  The language
> doesn't allow you to declare objects of an abstract type, so Func
> could not declare a local variable "Result" of type T1 that it could
> return.  Nor could it return an aggregate, which involves creating a
> temporary object.

Those things would have to be allowed, too.

>...In my view, the language model depends heavily on
> the assumption that an object can never be created whose tag refers to
> an abstract type; allowing the rule to *ever* be relaxed could be
> disastrous.

I don't think so.  As I posted a while back, the only trouble comes
from converting an object of an abstract type to a class-wide
type -- that is what needs to be forbidden.

Note to the OP:  You can also use the form of extension aggregate
where you give the ancestory type name.  In that case, you get
default initialization, which is unfortunate, but it does work.

- Bob


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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-21 19:09   ` Dan'l Miller
@ 2014-05-21 22:09     ` Robert A Duff
  2014-05-21 22:29       ` Adam Beneschan
  0 siblings, 1 reply; 13+ messages in thread
From: Robert A Duff @ 2014-05-21 22:09 UTC (permalink / raw)


"Dan'l Miller" <optikos@verizon.net> writes:

> The size of an abstract type is not known in this situation.

The size of the abstract type is know from the (possibly private) record
or record extension.

>>     package Pack1 is
>>         type T1 is abstract tagged record ... end record;
>>         function Func (X : Integer) return T1;  -- not currently legal
>
> This whole topic seems to be going nowhere fast.  The size of T1's
> eventual concrete type (i.e., some member of T1'Class) cannot be known
> by Func (nor in general by callers of Func).  There could be many such
> eventual concrete types of T1; hence the insurmountable question will
> always be: which member of T1'Class was instantiated concretely?

No, no, I think you are misunderstanding the suggested language change.
Func is returning a T1, whose size is perfectly well known to the
compiler.  It's not returning some other member of T1'Class.

Anyway, this:

  function Class_Wide_Func (X : Integer) return T1'Class;  -- currently legal

IS legal, and it CAN return an object whose tag is anything
in the class.  The size in this case is determined at the
"return" in the body.

- Bob

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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-21 22:09     ` Robert A Duff
@ 2014-05-21 22:29       ` Adam Beneschan
  0 siblings, 0 replies; 13+ messages in thread
From: Adam Beneschan @ 2014-05-21 22:29 UTC (permalink / raw)


On Wednesday, May 21, 2014 3:09:00 PM UTC-7, Robert A Duff wrote:

> Anyway, this:
> 
>   function Class_Wide_Func (X : Integer) return T1'Class;  -- currently legal
> 
> IS legal, and it CAN return an object whose tag is anything
> in the class.  The size in this case is determined at the
> "return" in the body.

"Anything" in the class--you mean anything that isn't an abstract type, I presume?  (And yes, I understand you're making a point about the size not needing to be known, and the reason we don't allow an abstract type to be returned has nothing to do with the size.)

                          -- Adam



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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-21 22:04   ` Robert A Duff
@ 2014-05-21 22:33     ` Adam Beneschan
  2014-05-21 23:19       ` Robert A Duff
  0 siblings, 1 reply; 13+ messages in thread
From: Adam Beneschan @ 2014-05-21 22:33 UTC (permalink / raw)


On Wednesday, May 21, 2014 3:04:05 PM UTC-7, Robert A Duff wrote:
> Adam Beneschan writes:

> >...In my view, the language model depends heavily on
> > the assumption that an object can never be created whose tag refers to
> > an abstract type; allowing the rule to *ever* be relaxed could be
> > disastrous.
> 
> I don't think so.  As I posted a while back, the only trouble comes
> from converting an object of an abstract type to a class-wide
> type -- that is what needs to be forbidden.

Hmmm... I'd worry that if we allowed an object with an abstract-type tag to exist even for a little while, something in the language semantics might require Initialize, Adjust, or Finalize to be called on it, which could be bad if, for example, it tried to redispatch to an abstract body.  (I don't remember the earlier conversation, so I don't know if this was dealt with already.)

                                  -- Adam

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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-21 22:33     ` Adam Beneschan
@ 2014-05-21 23:19       ` Robert A Duff
  2014-05-22  7:22         ` Dmitry A. Kazakov
  2014-05-22 14:47         ` Adam Beneschan
  0 siblings, 2 replies; 13+ messages in thread
From: Robert A Duff @ 2014-05-21 23:19 UTC (permalink / raw)


Adam Beneschan <adambeneschan@gmail.com> writes:

> Hmmm... I'd worry that if we allowed an object with an abstract-type
> tag to exist even for a little while, something in the language
> semantics might require Initialize, Adjust, or Finalize to be called
> on it, which could be bad if, for example, it tried to redispatch to
> an abstract body.

Not sure what you mean about "redispatch".  You can't [re]dispatch
without converting to class-wide.

But if (e.g.) Initialize itself is abstract, that would have to
be dealt with.  So it's not quite as simple as I made it out to be.

- Bob

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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-21 23:19       ` Robert A Duff
@ 2014-05-22  7:22         ` Dmitry A. Kazakov
  2014-05-24 18:39           ` Robert A Duff
  2014-05-22 14:47         ` Adam Beneschan
  1 sibling, 1 reply; 13+ messages in thread
From: Dmitry A. Kazakov @ 2014-05-22  7:22 UTC (permalink / raw)


On Wed, 21 May 2014 19:19:21 -0400, Robert A Duff wrote:

> Adam Beneschan <adambeneschan@gmail.com> writes:
> 
>> Hmmm... I'd worry that if we allowed an object with an abstract-type
>> tag to exist even for a little while, something in the language
>> semantics might require Initialize, Adjust, or Finalize to be called
>> on it, which could be bad if, for example, it tried to redispatch to
>> an abstract body.
> 
> Not sure what you mean about "redispatch".  You can't [re]dispatch
> without converting to class-wide.

Actually you can:

1. The Rosen's trick. You put a class-wide access discriminant into the
abstract type and dispatch on it.

2. Consider:

   type T is tagged ...;  -- Non-abstract
   type S is abstract new T with ...; -- Abstract

You convert to T, then that to T'Class and then dispatch on that. Never
needed S'Class to make it crash.

Morale. Type semantics must be respected.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-21 23:19       ` Robert A Duff
  2014-05-22  7:22         ` Dmitry A. Kazakov
@ 2014-05-22 14:47         ` Adam Beneschan
  2014-05-24 18:45           ` Robert A Duff
  1 sibling, 1 reply; 13+ messages in thread
From: Adam Beneschan @ 2014-05-22 14:47 UTC (permalink / raw)


On Wednesday, May 21, 2014 4:19:21 PM UTC-7, Robert A Duff wrote:

> Not sure what you mean about "redispatch".  You can't [re]dispatch
> without converting to class-wide.

It didn't occur to me until later that your idea about forbidding a conversion from an abstract type to a class-wide type has to be a run-time check, not a compile-time check (or not solely a compile-time check).  Otherwise, if an operation of a concrete type converts a controlling parameter to a class-wide type, and then an abstract type is derived without overriding the operation, the code would then be converting the abstract object to a class-wide type unless it were checked at run-time.

That's the sort of scenario I was thinking of when I mentioned Initialize/Adjust/Finalize doing a redispatch.

                               -- Adam


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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-22  7:22         ` Dmitry A. Kazakov
@ 2014-05-24 18:39           ` Robert A Duff
  2014-05-24 19:20             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 13+ messages in thread
From: Robert A Duff @ 2014-05-24 18:39 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On Wed, 21 May 2014 19:19:21 -0400, Robert A Duff wrote:
>> Not sure what you mean about "redispatch".  You can't [re]dispatch
>> without converting to class-wide.
>
> Actually you can:
>
> 1. The Rosen's trick. You put a class-wide access discriminant into the
> abstract type and dispatch on it.
>
> 2. Consider:
>
>    type T is tagged ...;  -- Non-abstract
>    type S is abstract new T with ...; -- Abstract
>
> You convert to T, then that to T'Class and then dispatch on that. Never
> needed S'Class to make it crash.

Good points.  I still think it could work, given certain restrictions.
I should have said, "You can't [re]dispatch without obtaining a
class-wide view."  That's what would need to be prevented.

> Morale. Type semantics must be respected.

?

- Bob


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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-22 14:47         ` Adam Beneschan
@ 2014-05-24 18:45           ` Robert A Duff
  0 siblings, 0 replies; 13+ messages in thread
From: Robert A Duff @ 2014-05-24 18:45 UTC (permalink / raw)


(sorry for email; I meant to post)

Adam Beneschan <adambeneschan@gmail.com> writes:

> On Wednesday, May 21, 2014 4:19:21 PM UTC-7, Robert A Duff wrote:
>
>> Not sure what you mean about "redispatch".  You can't [re]dispatch
>> without converting to class-wide.
>
> It didn't occur to me until later that your idea about forbidding a
> conversion from an abstract type to a class-wide type has to be a
> run-time check, not a compile-time check (or not solely a compile-time
> check).  Otherwise, if an operation of a concrete type converts a
> controlling parameter to a class-wide type, and then an abstract type
> is derived without overriding the operation, the code would then be
> converting the abstract object to a class-wide type unless it were
> checked at run-time.
>
> That's the sort of scenario I was thinking of when I mentioned
> Initialize/Adjust/Finalize doing a redispatch.

Ah, I see.  That's essentially the same as Dmitry's point 2.
I don't think it's specific to I/A/F.  Yes, it could be a
run-time check, but I'd much prefer a compile-time check,
even if it's rather restrictive.  Currently, dangling dispatch
is prevented by compile-time rules, and I'd like to keep it
that way.

- Bob

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

* Re: Suggestion: Allow functions returning abstract types in certain situations
  2014-05-24 18:39           ` Robert A Duff
@ 2014-05-24 19:20             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry A. Kazakov @ 2014-05-24 19:20 UTC (permalink / raw)


On Sat, 24 May 2014 14:39:12 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> Morale. Type semantics must be respected.
> 
> ?

No instances (abstract) means no instances. When typing gets broken you
never know where than may leak out. Ada would be a much safer language if
not these attempts to break typing for the sake imaginary advantages, which
never pay off.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

end of thread, other threads:[~2014-05-24 19:20 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-21 14:52 Suggestion: Allow functions returning abstract types in certain situations Victor Porton
2014-05-21 16:10 ` Adam Beneschan
2014-05-21 19:09   ` Dan'l Miller
2014-05-21 22:09     ` Robert A Duff
2014-05-21 22:29       ` Adam Beneschan
2014-05-21 22:04   ` Robert A Duff
2014-05-21 22:33     ` Adam Beneschan
2014-05-21 23:19       ` Robert A Duff
2014-05-22  7:22         ` Dmitry A. Kazakov
2014-05-24 18:39           ` Robert A Duff
2014-05-24 19:20             ` Dmitry A. Kazakov
2014-05-22 14:47         ` Adam Beneschan
2014-05-24 18:45           ` Robert A Duff

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