comp.lang.ada
 help / color / mirror / Atom feed
* Ada design bug or GNAT bug?
@ 2015-06-20 18:55 Dmitry A. Kazakov
  2015-06-21  2:42 ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-06-20 18:55 UTC (permalink / raw)


Is it intentional that there is no way to derive from a more specific type
privately? A key design pattern is no more possible in GNAT GPL 2015:

package P1 is
   type T1 is tagged null record;
   type T2 is new T1 with null record;
   function Foo return not null access T2;
end P1;

with P1; use P1;
package P2 is
   type T3 is new T1 with private;
private
   type T3 is new T2 with null record;
   overriding function Foo return not null access T3; -- Illegal!
end P2;

p2.ads:5:09: type must be declared abstract or "Foo" overridden
p2.ads:5:09: "Foo" has been inherited from subprogram at p1.ads:4
p2.ads:6:24: private function with tagged result must override visible-part
function
p2.ads:6:24: move subprogram to the visible part (RM 3.9.3(10))

[ Since when access types became tagged? ]

There seem no way to implement T3 by deriving from T2. *Any* declaration of
Foo would be illegal.

1. It cannot be inherited
2. A public declaration is not an overriding
3. A private declaration must be public

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

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

* Re: Ada design bug or GNAT bug?
  2015-06-20 18:55 Ada design bug or GNAT bug? Dmitry A. Kazakov
@ 2015-06-21  2:42 ` Randy Brukardt
  2015-06-21  6:47   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2015-06-21  2:42 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:yo94phsbcvht$.1bktwe2qoqntt$.dlg@40tude.net...
> Is it intentional that there is no way to derive from a more specific type
> privately? A key design pattern is no more possible in GNAT GPL 2015:
>
> package P1 is
>   type T1 is tagged null record;
>   type T2 is new T1 with null record;
>   function Foo return not null access T2;

Anonymous access types are evil; there cannot be a "key design" pattern 
using them. :-)

Since you did use an anonymous access result, you have a function with a 
"controlling access result". This works much like
   function Bar return T2;
which has a "controlling result".

If you had used a named access type, you definitely would not have this 
problem - 3.9.3(10/3) only applies to anonymous access types.

> end P1;
>
> with P1; use P1;
> package P2 is
>   type T3 is new T1 with private;
> private
>   type T3 is new T2 with null record;
>   overriding function Foo return not null access T3; -- Illegal!
> end P2;
>
> p2.ads:5:09: type must be declared abstract or "Foo" overridden
> p2.ads:5:09: "Foo" has been inherited from subprogram at p1.ads:4
> p2.ads:6:24: private function with tagged result must override 
> visible-part
> function
> p2.ads:6:24: move subprogram to the visible part (RM 3.9.3(10))
>
> [ Since when access types became tagged? ]

They're not "tagged", but they dispatch as if they were tagged (if 
anonymous). So they have to follow the same rules as with a tagged type.

> There seem no way to implement T3 by deriving from T2. *Any* declaration 
> of
> Foo would be illegal.
>
> 1. It cannot be inherited
> 2. A public declaration is not an overriding
> 3. A private declaration must be public

Right. The same would happen for the function Bar that I noted above.

But that just means that you can't hide T2. There's no good reason to not 
declare T3 as
   type T3 is new T2 with private;
and that eliminates any problem (you can then declare Foo anywhere you want 
in the spec).

Anyway, it's definitely *not* a design bug. It follows from the requirement 
that one can dispatch on the result; we can't allow dispatching to functions 
that return the wrong kind of thing. 6.5(8.1/3) would require any attempt to 
return the wrong kind of thing to raise Constraint_Error. That requires a 
new body and automatically generating one that always raises 
Constraint_Error would be madness. Thus the "shall be overridden" 
requirement.

Perhaps you didn't want to dispatch on the result, but too bad, that's how 
anonymous access designated tagged types is defined (it's supposed to be an 
exact equivalent of anonymous access parameters). If there's a design bug, 
it's the existence of anonymous access types at all with these unusual 
special properties.

Anyway, there are three workarounds: (1) don't hide T2; (2) use a named 
access type; (3) use a class-wide type for the return (thus turning off 
dispatching).

                            Randy.


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

* Re: Ada design bug or GNAT bug?
  2015-06-21  2:42 ` Randy Brukardt
@ 2015-06-21  6:47   ` Dmitry A. Kazakov
  2015-06-22 17:39     ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-06-21  6:47 UTC (permalink / raw)


On Sat, 20 Jun 2015 21:42:44 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:yo94phsbcvht$.1bktwe2qoqntt$.dlg@40tude.net...
>> Is it intentional that there is no way to derive from a more specific type
>> privately? A key design pattern is no more possible in GNAT GPL 2015:
>>
>> package P1 is
>>   type T1 is tagged null record;
>>   type T2 is new T1 with null record;
>>   function Foo return not null access T2;
> 
> Anonymous access types are evil; there cannot be a "key design" pattern 
> using them. :-)

The pattern is having an implementation privately deriving from a more
specific type, while the visible parent might be abstract or interface.

>> p2.ads:5:09: type must be declared abstract or "Foo" overridden
>> p2.ads:5:09: "Foo" has been inherited from subprogram at p1.ads:4
>> p2.ads:6:24: private function with tagged result must override 
>> visible-part function
>> p2.ads:6:24: move subprogram to the visible part (RM 3.9.3(10))
>>
>> [ Since when access types became tagged? ]
> 
> They're not "tagged", but they dispatch as if they were tagged (if 
> anonymous). So they have to follow the same rules as with a tagged type.

Then it should be said this way. I believe RM uses the word "controlling"
for this on other occasions.

>> There seem no way to implement T3 by deriving from T2. *Any* declaration 
>> of Foo would be illegal.
>>
>> 1. It cannot be inherited
>> 2. A public declaration is not an overriding
>> 3. A private declaration must be public
> 
> Right. The same would happen for the function Bar that I noted above.

Not exactly same, because for a tagged result the operation could be
inherited. For an access to tagged result it cannot be.

> But that just means that you can't hide T2.

Yep, that is the problem.

> There's no good reason to not 
> declare T3 as
>    type T3 is new T2 with private;
> and that eliminates any problem (you can then declare Foo anywhere you want 
> in the spec).

There are loads of good reasons to hide implementation details.

BTW, in the original code the type is declared unconstrained to prevent
unmanaged creation of objects. And the operation in question is not
intended to be used for the derived type.

> Anyway, it's definitely *not* a design bug. It follows from the requirement 
> that one can dispatch on the result; we can't allow dispatching to functions 
> that return the wrong kind of thing. 6.5(8.1/3) would require any attempt to 
> return the wrong kind of thing to raise Constraint_Error. That requires a 
> new body and automatically generating one that always raises 
> Constraint_Error would be madness. Thus the "shall be overridden" 
> requirement.

The function is not visible for public clients, they cannot call it.

> If there's a design bug, 
> it's the existence of anonymous access types at all with these unusual 
> special properties.

Maybe, but once introduced they should not break more important language
features, like information hiding.

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

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

* Re: Ada design bug or GNAT bug?
  2015-06-21  6:47   ` Dmitry A. Kazakov
@ 2015-06-22 17:39     ` Randy Brukardt
  2015-06-22 18:16       ` Dmitry A. Kazakov
  2015-06-22 18:27       ` Shark8
  0 siblings, 2 replies; 46+ messages in thread
From: Randy Brukardt @ 2015-06-22 17:39 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:4lrj5zz2u2z.u8x9cf7xzic6.dlg@40tude.net...
> On Sat, 20 Jun 2015 21:42:44 -0500, Randy Brukardt wrote:
...
>>> p2.ads:5:09: type must be declared abstract or "Foo" overridden
>>> p2.ads:5:09: "Foo" has been inherited from subprogram at p1.ads:4
>>> p2.ads:6:24: private function with tagged result must override
>>> visible-part function
>>> p2.ads:6:24: move subprogram to the visible part (RM 3.9.3(10))
>>>
>>> [ Since when access types became tagged? ]
>>
>> They're not "tagged", but they dispatch as if they were tagged (if
>> anonymous). So they have to follow the same rules as with a tagged type.
>
> Then it should be said this way. I believe RM uses the word "controlling"
> for this on other occasions.

The RM uses it in *this* occassion, too. Don't blame Ada for some 
implementation's confusing error messages!

...
>> If there's a design bug,
>> it's the existence of anonymous access types at all with these unusual
>> special properties.
>
> Maybe, but once introduced they should not break more important language
> features, like information hiding.

What part of "anonymous access types are evil" did you fail to understand?? 
:-) The mistake I regret more than any other was allowing their use to be 
expanded, for a purpose that doesn't really work, with semantics that are 
far more complex than anyone really wanted.

We don't have a choice about allowing hidden controlling results and 
controlling access results (unless, of course, we want to abandon real 
privacy, which we're not going to do). The only way to avoid that problem is 
to not have the feature at all (which is where I would stand). But as they 
exist, they have to work this way. Sorry.

                                   Randy.


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

* Re: Ada design bug or GNAT bug?
  2015-06-22 17:39     ` Randy Brukardt
@ 2015-06-22 18:16       ` Dmitry A. Kazakov
  2015-06-23 11:00         ` G.B.
                           ` (2 more replies)
  2015-06-22 18:27       ` Shark8
  1 sibling, 3 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-06-22 18:16 UTC (permalink / raw)


On Mon, 22 Jun 2015 12:39:16 -0500, Randy Brukardt wrote:

> We don't have a choice about allowing hidden controlling results and 
> controlling access results (unless, of course, we want to abandon real 
> privacy, which we're not going to do).

If function is invisible it is, and its result is as well.

> The only way to avoid that problem is 

Which problem is? The operation is not visible, it cannot be called.

> to not have the feature at all (which is where I would stand).

I don't see connection to anonymous access types, the rule applies to
tagged results as well:

package P1 is
   type T1 is tagged null record;
   type T2 is new T1 with null record;
   function Foo return T2;
end P1;

with P1; use P1;
package P2 is
   type T3 is new T1 with private;
private
   type T3 is new T2 with null record; -- Legal!
end P2;

with P1; use P1;
package P2 is
   type T3 is new T1 with private;
private
   type T3 is new T2 with null record;
   overriding function Foo return T3; -- ILLEGAL!
end P2;

As such the rule does not make any sense. You shall under no circumstance
prohibit overriding of inherited operations.

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

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

* Re: Ada design bug or GNAT bug?
  2015-06-22 17:39     ` Randy Brukardt
  2015-06-22 18:16       ` Dmitry A. Kazakov
@ 2015-06-22 18:27       ` Shark8
  2015-06-23 11:51         ` vincent.diemunsch
  2015-06-23 13:06         ` vincent.diemunsch
  1 sibling, 2 replies; 46+ messages in thread
From: Shark8 @ 2015-06-22 18:27 UTC (permalink / raw)


On Monday, June 22, 2015 at 11:39:17 AM UTC-6, Randy Brukardt wrote:
> 
> What part of "anonymous access types are evil" did you fail to understand?? 
> :-) The mistake I regret more than any other was allowing their use to be 
> expanded, for a purpose that doesn't really work, with semantics that are 
> far more complex than anyone really wanted.

Yes, anonymous accesses ARE pretty bad.
But this does bring up the question: what missteps have been made in Ada's design?

Here's a few I can think of: 
* Ada's lack of the ability to derive from a private type in the same package. (Aspects now allow us to specify the interface info [like Size or convention] at the point of declaration; arguably in a new language this would be required in some new Ada-derived language where the defaults are altered.)
* Ada's inability to define subtypes on an enumeration where the enumeration has a representation-clause in the private part.
* Ada95's modular types combine the orthogonal idea of a cyclic numeric type and an unsigned type -- conceptually it could have been better to separate the two.
* Ada95's Representation clauses lack the ability to specify byte-order, though they do offer bit-order.
* The lack of a "abstract type" that could be used to unify (e.g.) [[Wide_[Wide_]]String into a single "generic"/abstract type; ditto on Character.

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

* Re: Ada design bug or GNAT bug?
  2015-06-22 18:16       ` Dmitry A. Kazakov
@ 2015-06-23 11:00         ` G.B.
  2015-06-23 14:27           ` Dmitry A. Kazakov
  2015-06-23 11:45         ` G.B.
  2015-07-02 22:22         ` Randy Brukardt
  2 siblings, 1 reply; 46+ messages in thread
From: G.B. @ 2015-06-23 11:00 UTC (permalink / raw)


On 22.06.15 20:16, Dmitry A. Kazakov wrote:
> Which problem is? The operation is not visible, it cannot be called.

Am I missing something?


package body P2.Child is
    X : T3;
    Y : T1'Class := T3'(Foo);
begin
    X := Foo;
end P2.Child;


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

* Re: Ada design bug or GNAT bug?
  2015-06-22 18:16       ` Dmitry A. Kazakov
  2015-06-23 11:00         ` G.B.
@ 2015-06-23 11:45         ` G.B.
  2015-06-23 14:30           ` Dmitry A. Kazakov
  2015-07-02 22:22         ` Randy Brukardt
  2 siblings, 1 reply; 46+ messages in thread
From: G.B. @ 2015-06-23 11:45 UTC (permalink / raw)


On 22.06.15 20:16, Dmitry A. Kazakov wrote:

> with P1; use P1;
> package P2 is
>     type T3 is new T1 with private;
> private
>     type T3 is new T2 with null record;
>     overriding function Foo return T3; -- ILLEGAL!
> end P2;


Would this do, as it is, oddly maybe, accepted:

with P1;
package P22 is
    type T3 is new P1.T1 with private;
private
    package Layer is
       type T22 is new P1.T2 with null record;
    private
       overriding function Foo return T22;
    end Layer;
    type T3 is new Layer.T22 with null record;
end P22;

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

* Re: Ada design bug or GNAT bug?
  2015-06-22 18:27       ` Shark8
@ 2015-06-23 11:51         ` vincent.diemunsch
  2015-06-23 19:55           ` Shark8
  2015-06-23 13:06         ` vincent.diemunsch
  1 sibling, 1 reply; 46+ messages in thread
From: vincent.diemunsch @ 2015-06-23 11:51 UTC (permalink / raw)


Le lundi 22 juin 2015 20:27:17 UTC+2, Shark8 a écrit :

> * Ada95's modular types combine the orthogonal idea of a cyclic numeric type and an unsigned type -- conceptually it could have been better to separate the two.

Could you tell us a bit more on that ? Why would it be better to separate Unsigned Integer and modular types ? I had the impression that a compiler could use a unsigned integer representation for such integer declaration :

type Unsigned is range 0 .. 2**32 -1;

Since converting to a Standard.Integer requires anyway to use an explicit
conversion in the Ada language because of strong typing, not mentionning run-time tests on range, I thought it would be easy for the compiler to insert conversion between signed and unsigned.

But it seems that Ada implementations prefer to use 

type Unsigned is mod 2**32;

But what is the problem with this ? Detection of overflow ?



> * The lack of a "abstract type" that could be used to unify (e.g.) [[Wide_[Wide_]]String into a single "generic"/abstract type; ditto on Character.

Same question : what would be your proposal ?

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

* Re: Ada design bug or GNAT bug?
  2015-06-22 18:27       ` Shark8
  2015-06-23 11:51         ` vincent.diemunsch
@ 2015-06-23 13:06         ` vincent.diemunsch
  2015-06-23 14:30           ` David Botton
                             ` (3 more replies)
  1 sibling, 4 replies; 46+ messages in thread
From: vincent.diemunsch @ 2015-06-23 13:06 UTC (permalink / raw)


Le lundi 22 juin 2015 20:27:17 UTC+2, Shark8 a écrit :
> 
> Yes, anonymous accesses ARE pretty bad.
> But this does bring up the question: what missteps have been made in Ada's design?
> 

I regard the refusal to create a "class type", like Ichbiah wanted it, just like we have a protected type and a task type, as the root of evil. For the OOP concept is based on an interface that is the same and instances that are different realizations of the same concept. So we need to have two objects : 
- a class object that is an interface and manage memory (a descendant of controlled type)
- an instance object that is polymorphic.

One may think that the distinction between class type and tagged type is subtle, but the implications of it are huge : without class object one needs as replacement access to a class wide type. This has led to the use of access values everywhere when doing OOP. To ease the pain access parameters and anonymous access types were introduced...

Regards,

Vincent


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

* Re: Ada design bug or GNAT bug?
  2015-06-23 11:00         ` G.B.
@ 2015-06-23 14:27           ` Dmitry A. Kazakov
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-06-23 14:27 UTC (permalink / raw)


On Tue, 23 Jun 2015 13:00:17 +0200, G.B. wrote:

> On 22.06.15 20:16, Dmitry A. Kazakov wrote:
>> Which problem is? The operation is not visible, it cannot be called.
> 
> Am I missing something?
> 
> package body P2.Child is
>     X : T3;
>     Y : T1'Class := T3'(Foo);
> begin
>     X := Foo;
> end P2.Child;

This is a private view of T3. A private client has full view of everything
and thus there should no problem anyway. To my understanding Randy meant
some unclear to me problems with public clients. 

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

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

* Re: Ada design bug or GNAT bug?
  2015-06-23 11:45         ` G.B.
@ 2015-06-23 14:30           ` Dmitry A. Kazakov
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-06-23 14:30 UTC (permalink / raw)


On Tue, 23 Jun 2015 13:45:35 +0200, G.B. wrote:

> On 22.06.15 20:16, Dmitry A. Kazakov wrote:
> 
>> with P1; use P1;
>> package P2 is
>>     type T3 is new T1 with private;
>> private
>>     type T3 is new T2 with null record;
>>     overriding function Foo return T3; -- ILLEGAL!
>> end P2;
> 
> Would this do, as it is, oddly maybe, accepted:
> 
> with P1;
> package P22 is
>     type T3 is new P1.T1 with private;
> private
>     package Layer is
>        type T22 is new P1.T2 with null record;
>     private
>        overriding function Foo return T22;
>     end Layer;
>     type T3 is new Layer.T22 with null record;
> end P22;

You must ask Randy, as he sees problems with overriding Foo. You might be
fool the compiler into accepting something that should be unacceptable
according to him. My point was that having it unacceptable was a language
design bug, access types or not regardless.

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


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

* Re: Ada design bug or GNAT bug?
  2015-06-23 13:06         ` vincent.diemunsch
@ 2015-06-23 14:30           ` David Botton
  2015-06-23 15:57             ` Niklas Holsti
  2015-06-23 14:38           ` Dmitry A. Kazakov
                             ` (2 subsequent siblings)
  3 siblings, 1 reply; 46+ messages in thread
From: David Botton @ 2015-06-23 14:30 UTC (permalink / raw)


> I regard the refusal to create a "class type", like Ichbiah wanted it

At this point, we all know it was a mistake and the experiences of the last years and revisions have also showed areas were things can be simplified and improved.

Perhaps it is time to rethink Ada not just add some more patches on and not worry about backward compatibility.

David Botton


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

* Re: Ada design bug or GNAT bug?
  2015-06-23 13:06         ` vincent.diemunsch
  2015-06-23 14:30           ` David Botton
@ 2015-06-23 14:38           ` Dmitry A. Kazakov
  2015-06-23 16:57             ` Vincent
  2015-06-23 17:42           ` Jeffrey R. Carter
  2015-07-02 22:06           ` Randy Brukardt
  3 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-06-23 14:38 UTC (permalink / raw)


On Tue, 23 Jun 2015 06:06:13 -0700 (PDT), vincent.diemunsch@gmail.com
wrote:

> I regard the refusal to create a "class type", like Ichbiah wanted it,
> just like we have a protected type and a task type, as the root of evil.

Ada's was is the only consistent way.

> For the OOP concept is based on an interface that is the same and
> instances that are different realizations of the same concept.

This is an inconsistent concept if taken literally. OOP never talk about
types being same. It does about same *behavior*. This is miles over miles
different. T and T'Class behave as if they were same in some contexts, but
they are not same from any point of view. Remember that class is a set of
types. A set is never equal to its instances. T'Class is a closure of
class. Closure of a set is not equal to an element of the set.

> One may think that the distinction between class type and tagged type is
> subtle, but the implications of it are huge : without class object one
> needs as replacement access to a class wide type.

Why?

(Access types appeared for having the Rosen's trick and working around
missing proper constructors and destructors.)

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


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

* Re: Ada design bug or GNAT bug?
  2015-06-23 14:30           ` David Botton
@ 2015-06-23 15:57             ` Niklas Holsti
  2015-06-23 16:01               ` G.B.
                                 ` (2 more replies)
  0 siblings, 3 replies; 46+ messages in thread
From: Niklas Holsti @ 2015-06-23 15:57 UTC (permalink / raw)


On 15-06-23 17:30 , David Botton wrote:
>> I regard the refusal to create a "class type", like Ichbiah wanted it
>
> At this point, we all know it was a mistake

No we don't.

> and the experiences of the last years and revisions have also
> showed areas were things can be simplified and improved.

Sure.

> Perhaps it is time to rethink Ada not just add some more patches
> on and not worry about backward compatibility.

That would certainly be interesting. But any rethink should, IMO, result 
in an Ada-noveau that is even more "Ada-like", and so perhaps even less 
similar to other, more popular languages.

The question is if the rather frail thread of Ada life-force could stand 
being divided into two camps, old Ada and Ada-noveau. Perhaps we can 
hope that Ada-noveau will be much simpler and therefore easier to 
implement, perhaps through more automatic generation of compilation 
phases from formal semantics.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

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

* Re: Ada design bug or GNAT bug?
  2015-06-23 15:57             ` Niklas Holsti
@ 2015-06-23 16:01               ` G.B.
  2015-06-23 18:05               ` David Botton
  2015-06-23 19:38               ` David Botton
  2 siblings, 0 replies; 46+ messages in thread
From: G.B. @ 2015-06-23 16:01 UTC (permalink / raw)


On 23.06.15 17:57, Niklas Holsti wrote:
> Perhaps we can hope that Ada-noveau will be much simpler and therefore
> easier to implement, perhaps through more automatic generation of
> compilation phases from formal semantics.

The approach taken by Ada, like that taken by some
former Scheme, is pragma Profile ;-)

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

* Re: Ada design bug or GNAT bug?
  2015-06-23 14:38           ` Dmitry A. Kazakov
@ 2015-06-23 16:57             ` Vincent
  2015-06-23 17:15               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Vincent @ 2015-06-23 16:57 UTC (permalink / raw)


Le mardi 23 juin 2015 16:38:43 UTC+2, Dmitry A. Kazakov a écrit :
 > > For the OOP concept is based on an interface that is the same and
> > instances that are different realizations of the same concept.
> 
> This is an inconsistent concept if taken literally. OOP never talk about
> types being same. It does about same *behavior*. This is miles over miles
> different. T and T'Class behave as if they were same in some contexts, but
> they are not same from any point of view. Remember that class is a set of
> types. A set is never equal to its instances. T'Class is a closure of
> class. Closure of a set is not equal to an element of the set.

A would rather call a set of types a category [of types], like Integers or
dicrete types. A class type is an accessor to a category consisting of a given type and all types derived from it.

 
> > One may think that the distinction between class type and tagged type is
> > subtle, but the implications of it are huge : without class object one
> > needs as replacement access to a class wide type.
> 
> Why?
> 

Because one need a concrete object ! With generics you can have a formal type because it will be instantiated during the early phase of compilation, but with OOP the code is generated before one knows the type of the object that will be called at runtime. Strictly speaking this is not possible. The only possible solution is to use a unique object as an accessor for all possible objects. The simplest way was to use an access to a class wide type. But Ada 83 limited the use of access types to pool specific types...

Regards,

Vincent



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

* Re: Ada design bug or GNAT bug?
  2015-06-23 16:57             ` Vincent
@ 2015-06-23 17:15               ` Dmitry A. Kazakov
  2015-06-23 19:14                 ` vincent.diemunsch
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-06-23 17:15 UTC (permalink / raw)


On Tue, 23 Jun 2015 09:57:43 -0700 (PDT), Vincent wrote:

> Le mardi 23 juin 2015 16:38:43 UTC+2, Dmitry A. Kazakov a écrit :
>  > > For the OOP concept is based on an interface that is the same and
>>> instances that are different realizations of the same concept.
>> 
>> This is an inconsistent concept if taken literally. OOP never talk about
>> types being same. It does about same *behavior*. This is miles over miles
>> different. T and T'Class behave as if they were same in some contexts, but
>> they are not same from any point of view. Remember that class is a set of
>> types. A set is never equal to its instances. T'Class is a closure of
>> class. Closure of a set is not equal to an element of the set.
> 
> A would rather call a set of types a category [of types], like Integers or
> dicrete types.

Integers is a class of types, so discrete types are.

> A class type is an accessor to a category consisting of a given type and
> all types derived from it.

That is a parent type, which is just a type as any other.

The set of types bound by some relation (e.g. inheritance) is a class. The
class type as T'Class, is a type corresponding to the closure of the set
using the relation.

>>> One may think that the distinction between class type and tagged type is
>>> subtle, but the implications of it are huge : without class object one
>>> needs as replacement access to a class wide type.
>> 
>> Why?
> 
> Because one need a concrete object!

tagged object is a concrete object.

> With generics you can have a formal
> type because it will be instantiated during the early phase of
> compilation, but with OOP the code is generated before one knows the type
> of the object that will be called at runtime.

Ada supports shared generic bodies. For them code is generated before
instantiation.

> Strictly speaking this is not possible.

I don't know what you mean. The difference between static and dynamic
polymorphism is not when and how the code is being generated.

> The only possible solution is to use a unique object as an
> accessor for all possible objects.

A solution for what? Why there should be common ancestor of a polymorphic
class (set of types). There could be type systems when two types are mutual
ancestors and descendants of each other. The inheritance graph is not
necessarily a tree.

> The simplest way was to use an access
> to a class wide type.

Access type is not an ancestor of target types. In a better Ada it could be
descendant or a subtype, but not in present Ada.

> But Ada 83 limited the use of access types to pool specific types...

Ada 83 didn't mentioned pools.

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

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

* Re: Ada design bug or GNAT bug?
  2015-06-23 13:06         ` vincent.diemunsch
  2015-06-23 14:30           ` David Botton
  2015-06-23 14:38           ` Dmitry A. Kazakov
@ 2015-06-23 17:42           ` Jeffrey R. Carter
  2015-07-02 22:06           ` Randy Brukardt
  3 siblings, 0 replies; 46+ messages in thread
From: Jeffrey R. Carter @ 2015-06-23 17:42 UTC (permalink / raw)


Shark8 wrote :
>
> Yes, anonymous accesses ARE pretty bad.
> But this does bring up the question: what missteps have been made in Ada's design?

In addition to those listed by Shark8, I would add:

* Combining the concepts of ":=" and "=": private types have both by default,
and limited types have neither.

* Private parts, rather than full views in the body.

* Anonymous types.

* Features for programming by extension (tagged types and child pkgs that extend
their parents).

* Introducing protected types with arbitrary and unnecessary restrictions on
what they can do, rather than formalizing the passive-task concept.

And probably others I can't think of right now.

-- 
Jeff Carter
"When Bell Labs were invited to evaluate C against the DoD requirements
[for Ada], they said that there was no chance of C meeting the
requirements of readability, safety, etc. for which we were striving,
and that it should not even be on the list of evaluated languages."
William Whitaker
116


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

* Re: Ada design bug or GNAT bug?
  2015-06-23 15:57             ` Niklas Holsti
  2015-06-23 16:01               ` G.B.
@ 2015-06-23 18:05               ` David Botton
  2015-06-23 19:38               ` David Botton
  2 siblings, 0 replies; 46+ messages in thread
From: David Botton @ 2015-06-23 18:05 UTC (permalink / raw)



> No we don't.

There will always be those that disagree and even I am not convinced that a "class type" per se is the right change today, just what was implemented was less than ideal and the result, is Ichbiah foresaw, cost the language in terms of traction when timing was critical.

So a rethink does not per se mean an embrace of former discarded decisions either, it means a fresh look. In today's market OOP matters far less and its hype vs. value is now balanced.

>The approach taken by Ada, like that taken by some 
former Scheme, is pragma Profile ;-) 

Agreed and those wanting backward compatibility can always have it in those packages needed.

Perhaps a simplification may even make implementing new front ends more reasonable an effort to leverage new tech GCC is not reaching and not likely to reach ever.

David Botton


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

* Re: Ada design bug or GNAT bug?
  2015-06-23 17:15               ` Dmitry A. Kazakov
@ 2015-06-23 19:14                 ` vincent.diemunsch
  2015-06-23 19:33                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: vincent.diemunsch @ 2015-06-23 19:14 UTC (permalink / raw)


Le mardi 23 juin 2015 19:15:36 UTC+2, Dmitry A. Kazakov a écrit :

> On Tue, 23 Jun 2015 09:57:43 -0700 (PDT), Vincent wrote:
> > A would rather call a set of types a category [of types], like Integers or
> > dicrete types.
> 
> Integers is a class of types, so discrete types are.

Ok ARM 2012 says :
Any set of types can be called a "category" of types, and any set of types that is closed under derivation (see 3.4) can be called a "class" of types. 

But I was trying to imagine a new category : a "class type". It would be something between :
- a general access-to-class-wide type
- a controlled object with Initialize, Adjust and Finalize.
- a protected type for the syntax of primitive operations

> >>> One may think that the distinction between class type and tagged type is
> >>> subtle, but the implications of it are huge : without class object one
> >>> needs as replacement access to a class wide type.
> >> 
> >> Why?
> > 
> > Because one need a concrete object!
> 
> tagged object is a concrete object.

Ok. I should have said, very often one need a constrained object,
and this requires an access value for polymorphic tagged objects. 

 Vincent

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

* Re: Ada design bug or GNAT bug?
  2015-06-23 19:14                 ` vincent.diemunsch
@ 2015-06-23 19:33                   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-06-23 19:33 UTC (permalink / raw)


On Tue, 23 Jun 2015 12:14:44 -0700 (PDT), vincent.diemunsch@gmail.com
wrote:

> Le mardi 23 juin 2015 19:15:36 UTC+2, Dmitry A. Kazakov a écrit :
> 
>> On Tue, 23 Jun 2015 09:57:43 -0700 (PDT), Vincent wrote:
>>> A would rather call a set of types a category [of types], like Integers or
>>> dicrete types.
>> 
>> Integers is a class of types, so discrete types are.
> 
> Ok ARM 2012 says :
> Any set of types can be called a "category" of types, and any set of types
> that is closed under derivation (see 3.4) can be called a "class" of
> types. 

RM 83 calls it class of types (see 3.3). But that does not matter. I don't
care about wording RM uses, meanings is what I care.

> But I was trying to imagine a new category : a "class type". It would be something between :
> - a general access-to-class-wide type
> - a controlled object with Initialize, Adjust and Finalize.
> - a protected type for the syntax of primitive operations

What for? Any type is a set of values and operations defined on them.
T'Class is necessary because there must be a type which values are from the
closure (union of all sets of values of types derived from T). OOPL's
mixing T and T'Class are inconsistent because sets of values are different.
These two cannot be same type.

When you want to introduce a type just start with its values and its
operations.

>>>>> One may think that the distinction between class type and tagged type is
>>>>> subtle, but the implications of it are huge : without class object one
>>>>> needs as replacement access to a class wide type.
>>>> 
>>>> Why?
>>> 
>>> Because one need a concrete object!
>> 
>> tagged object is a concrete object.
> 
> Ok. I should have said, very often one need a constrained object,
> and this requires an access value for polymorphic tagged objects. 

Why?

How this is even related to constraints? Constraint is a property of a set
of types when for each given constraint there is a type. Yes, Ada RM does
not call it "class", but that is RM's problem. A constrained subtype is a
type. The sets of all constrained subtypes is a class. The type with values
having different constraints is class-wide. Just another method of having
classes, nothing more.

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

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

* Re: Ada design bug or GNAT bug?
  2015-06-23 15:57             ` Niklas Holsti
  2015-06-23 16:01               ` G.B.
  2015-06-23 18:05               ` David Botton
@ 2015-06-23 19:38               ` David Botton
  2 siblings, 0 replies; 46+ messages in thread
From: David Botton @ 2015-06-23 19:38 UTC (permalink / raw)


> But any rethink should, IMO, result 
> in an Ada-noveau that is even more "Ada-like", and so perhaps even less 
> similar to other, more popular languages.

Very agreed. What makes Ada, Ada to me is:

_Readability_
Type System, subtypes and non aliased new types
Clear interface language for subprograms
Nested blocks with exceptions allowing greater use of the stack and minimizing need for memory management by the programmer
Integration of concurrency features in to the core language
Exact, clear, readable ways to map memory to types
Packaging

David Botton


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

* Re: Ada design bug or GNAT bug?
  2015-06-23 11:51         ` vincent.diemunsch
@ 2015-06-23 19:55           ` Shark8
  0 siblings, 0 replies; 46+ messages in thread
From: Shark8 @ 2015-06-23 19:55 UTC (permalink / raw)


On Tuesday, June 23, 2015 at 5:51:13 AM UTC-6, vincent....@gmail.com wrote:
> Le lundi 22 juin 2015 20:27:17 UTC+2, Shark8 a écrit :
> 
> > * Ada95's modular types combine the orthogonal idea of a cyclic numeric type and an unsigned type -- conceptually it could have been better to separate the two.
> 
> Could you tell us a bit more on that ? Why would it be better to separate Unsigned Integer and modular types ? I had the impression that a compiler could use a unsigned integer representation for such integer declaration :
> 
> type Unsigned is range 0 .. 2**32 -1;

Well, the simplest example would be clock time:
    Type CIVIL_HOUR is range 1..12 --...with some way to indicate cyclic.

Obviously here we have a numeric type that needs to cycle, but which has a 'First of non-zero and lies completely in POSITIVE.

> Since converting to a Standard.Integer requires anyway to use an explicit
> conversion in the Ada language because of strong typing, not mentionning run-time tests on range, I thought it would be easy for the compiler to insert conversion between signed and unsigned.

"Easy" might not be the right word, but 'doable' I think fits.

> But it seems that Ada implementations prefer to use 
> 
> type Unsigned is mod 2**32;
> 
> But what is the problem with this ? Detection of overflow ?

No, overflow is not a problem here, the MOD is indicating that the values of the type are cyclic... the problem is that this implicitly makes 'First 0 and there's no way to indicate that the cycle doesn't start at 0.

> > * The lack of a "abstract type" that could be used to unify (e.g.) [[Wide_[Wide_]]String into a single "generic"/abstract type; ditto on Character.
> 
> Same question : what would be your proposal ?

I'm not great [or even good] at language-design, but I would think something along the lines of how we contract generics via the generic's parameters only instead of operating on subprograms/packages it would be types themselves.

Perhaps something like:

   -- Analog of:
   -- Generic
   --   Type Actual is (<>);
   -- ...
   Abstract Type Abstract_Character is (<>);
   
   -- Analog of:
   -- Generic
   --   Type Element is (<>);
   --   Type Index is (<>);
   --   Type Actual is Array(Index range <>) of Element;
   -- ...
   Abstract Type Abstract_String( Positive Range <> ) of Abstract_Character;

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

* Re: Ada design bug or GNAT bug?
  2015-06-23 13:06         ` vincent.diemunsch
                             ` (2 preceding siblings ...)
  2015-06-23 17:42           ` Jeffrey R. Carter
@ 2015-07-02 22:06           ` Randy Brukardt
  2015-07-04  1:52             ` Shark8
  2015-07-06 12:37             ` Vincent
  3 siblings, 2 replies; 46+ messages in thread
From: Randy Brukardt @ 2015-07-02 22:06 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2051 bytes --]


<vincent.diemunsch@gmail.com> wrote in message 
news:58f64fa9-7d0b-44dd-870c-77d9afcb82c4@googlegroups.com...
Le lundi 22 juin 2015 20:27:17 UTC+2, Shark8 a écrit :
>>
>> Yes, anonymous accesses ARE pretty bad.
>> But this does bring up the question: what missteps have been made in 
>> Ada's design?
>>
>
>I regard the refusal to create a "class type", like Ichbiah wanted it, just 
>like we have a
> protected type and a task type, as the root of evil.

The type Ichbiah wanted was syntactic sugar only. The semantics would have 
been very similar to that of tagged types. The primary difference would have 
been that we wouldn't have had to wait for Ada 2005 to get prefix calls.

> For the OOP concept is based on
> an interface that is the same and instances that are different 
> realizations of the same
> concept. So we need to have two objects :
>- a class object that is an interface and manage memory (a descendant of 
>controlled type)
>- an instance object that is polymorphic.
>
>One may think that the distinction between class type and tagged type is 
>subtle, but the
>implications of it are huge : without class object one needs as replacement 
>access to a
>class wide type. This has led to the use of access values everywhere when 
>doing OOP.
>To ease the pain access parameters and anonymous access types were 
>introduced...

This seems to me to be nonsense. There's no need to use access types in Ada 
OOP interfaces; "in out T" and "access T" have virtually the same semantics 
when T is a tagged type. (Claw only has one access type in its entire 
interface, used for a return type that ought to be by reference. Everything 
else does not use visible access types.) It's more work this way, but it's 
definitely possible.

The reason Ada has anonymous access parameters was a desire (for Ada 9x) 
that code from existing OOP languages like C++ could be directly converted 
to Ada without having to think at all (thinking being necessary to get rid 
of access types).

                                               Randy.



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

* Re: Ada design bug or GNAT bug?
  2015-06-22 18:16       ` Dmitry A. Kazakov
  2015-06-23 11:00         ` G.B.
  2015-06-23 11:45         ` G.B.
@ 2015-07-02 22:22         ` Randy Brukardt
  2015-07-03  8:02           ` Dmitry A. Kazakov
  2 siblings, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2015-07-02 22:22 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:ykiyl6yc44or$.19365hv76bzoi.dlg@40tude.net...
> On Mon, 22 Jun 2015 12:39:16 -0500, Randy Brukardt wrote:
>
>> We don't have a choice about allowing hidden controlling results and
>> controlling access results (unless, of course, we want to abandon real
>> privacy, which we're not going to do).
>
> If function is invisible it is, and its result is as well.

Not really, because you can still dispatch to it (if the dispatching is 
somewhere that the private function is visible); dispatching does not 
respect privacy (as privacy is only a compile-time, not runtime, concept).

I realize that you hate redispatching (a point that I tend to agree with you 
on), but it's possible, and it's needed some part of the time (maybe 10% or 
even less, but more than 0%), so it exists and has to be taken into account.

>> The only way to avoid that problem is
>
> Which problem is? The operation is not visible, it cannot be called.

It surely can be called where it is visible, else it isn't very useful!

>> have the feature at all (which is where I would stand).
>
> I don't see connection to anonymous access types, the rule applies to
> tagged results as well:
>
> package P1 is
>   type T1 is tagged null record;
>   type T2 is new T1 with null record;
>   function Foo return T2;
> end P1;
>
> with P1; use P1;
> package P2 is
>   type T3 is new T1 with private;
> private
>   type T3 is new T2 with null record; -- Legal!

This is only legal because of a hack, which I was very much against 
introducing. If you have an extension component, this is illegal:

    type T4 is new T2 with record C : Character := '1'; end record; --  
Illegal!!!

> end P2;

I have tried to find a way to avoid this maintenance hazard (it's especially 
bad for mix-in generics), but I haven't gotten any traction to date. We 
could (if all of the extension components have defaults) automatically do 
this as we do for null record, but the problem is that making overriding 
required often detects bugs (failure to create a proper overriding). Plus 
the problem of incompatibility (only in obscure cases).

> with P1; use P1;
> package P2 is
>   type T3 is new T1 with private;
> private
>   type T3 is new T2 with null record;
>   overriding function Foo return T3; -- ILLEGAL!
> end P2;
>
> As such the rule does not make any sense. You shall under no circumstance
> prohibit overriding of inherited operations.

That's only possible if you prohibit any extensions of T3. (Otherwise, you 
get the dispatching problems that I noted previously, or you have to break 
privacy by making the derived type illegal for something that is not 
visible.) We've talked a bit about having such an aspect, but it is messy.

To summarize: it's a bad interaction between privacy and things that require 
overriding (abstract subprograms follow the same rules for the same 
reasons). There's no real solution, else you could call abstract 
subprograms -- and then what??

                                          Randy.




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

* Re: Ada design bug or GNAT bug?
  2015-07-02 22:22         ` Randy Brukardt
@ 2015-07-03  8:02           ` Dmitry A. Kazakov
  2015-07-03 17:33             ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-07-03  8:02 UTC (permalink / raw)


On Thu, 2 Jul 2015 17:22:08 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:ykiyl6yc44or$.19365hv76bzoi.dlg@40tude.net...
>> On Mon, 22 Jun 2015 12:39:16 -0500, Randy Brukardt wrote:
>>
>>> We don't have a choice about allowing hidden controlling results and
>>> controlling access results (unless, of course, we want to abandon real
>>> privacy, which we're not going to do).
>>
>> If function is invisible it is, and its result is as well.
> 
> Not really, because you can still dispatch to it (if the dispatching is 
> somewhere that the private function is visible); dispatching does not 
> respect privacy (as privacy is only a compile-time, not runtime, concept).

I don't see a scenario where you could dispatch on an invisible primitive
operation. First you must get into a context where you would have a view of
your type having that operation. This context cannot exist without another
context where the type gets derived. In that context you must have
overridden the operation. Where is a problem? Is it related to MI? [But Ada
does not respect privacy, when it checks inherited stuff, it does this as
if in a full view of the type, which is another language bug, but still no
problem.]

> I realize that you hate redispatching (a point that I tend to agree with you 
> on), but it's possible, and it's needed some part of the time (maybe 10% or 
> even less, but more than 0%), so it exists and has to be taken into account.

But even if you convert to the class-wide you don't get visibility of the
operation. In the scenario:

   type T3 is new T1 with private;
private
   type T3 is new T2 with null record; -- Legal!

a public client could not convert a T3 object to T2'Class. Could it?

>>> have the feature at all (which is where I would stand).
>>
>> I don't see connection to anonymous access types, the rule applies to
>> tagged results as well:
>>
>> package P1 is
>>   type T1 is tagged null record;
>>   type T2 is new T1 with null record;
>>   function Foo return T2;
>> end P1;
>>
>> with P1; use P1;
>> package P2 is
>>   type T3 is new T1 with private;
>> private
>>   type T3 is new T2 with null record; -- Legal!
> 
> This is only legal because of a hack, which I was very much against 
> introducing. If you have an extension component, this is illegal:
> 
>     type T4 is new T2 with record C : Character := '1'; end record; --  
> Illegal!!!

Yes, the hack you mean is contravariance of an out argument or result based
on a guess about the type implementation (null extension). It is wrong from
the strong typing POV.

>> end P2;
> 
> I have tried to find a way to avoid this maintenance hazard (it's especially 
> bad for mix-in generics), but I haven't gotten any traction to date. We 
> could (if all of the extension components have defaults) automatically do 
> this as we do for null record, but the problem is that making overriding 
> required often detects bugs (failure to create a proper overriding). Plus 
> the problem of incompatibility (only in obscure cases).

No. I know you don't believe in science and proofs but still, conravariance
in outputs is just wrong (under type extension). 

Instead of ugly hacks we better have had some delegation/body-composition
methods at the declaration place to be able to tell that the overriding is
basically the parent's implementation. We already allowed such stuff, e.g.

   procedure Foo (...) is null;

We have ugly executable precondition code at the declaration side. Why not
to allow this for functions?

>> with P1; use P1;
>> package P2 is
>>   type T3 is new T1 with private;
>> private
>>   type T3 is new T2 with null record;
>>   overriding function Foo return T3; -- ILLEGAL!
>> end P2;
>>
>> As such the rule does not make any sense. You shall under no circumstance
>> prohibit overriding of inherited operations.
> 
> That's only possible if you prohibit any extensions of T3. (Otherwise, you 
> get the dispatching problems that I noted previously, or you have to break 
> privacy by making the derived type illegal for something that is not 
> visible.) We've talked a bit about having such an aspect, but it is messy.

Could you provide an example of dispatching problems you have in mind?

> To summarize: it's a bad interaction between privacy and things that require 
> overriding (abstract subprograms follow the same rules for the same 
> reasons). There's no real solution, else you could call abstract 
> subprograms -- and then what??

Honestly I never understood how that could happen. The dispatching table
must be defined for any non-abstract instance. This is statically enforced,
isn't it?

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


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

* Re: Ada design bug or GNAT bug?
  2015-07-03  8:02           ` Dmitry A. Kazakov
@ 2015-07-03 17:33             ` Randy Brukardt
  2015-07-03 21:34               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2015-07-03 17:33 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1oyc7ksu2lrwz.1h4pqchzcyfzt.dlg@40tude.net...
> On Thu, 2 Jul 2015 17:22:08 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:ykiyl6yc44or$.19365hv76bzoi.dlg@40tude.net...
>>> On Mon, 22 Jun 2015 12:39:16 -0500, Randy Brukardt wrote:
>>>
>>>> We don't have a choice about allowing hidden controlling results and
>>>> controlling access results (unless, of course, we want to abandon real
>>>> privacy, which we're not going to do).
>>>
>>> If function is invisible it is, and its result is as well.
>>
>> Not really, because you can still dispatch to it (if the dispatching is
>> somewhere that the private function is visible); dispatching does not
>> respect privacy (as privacy is only a compile-time, not runtime, 
>> concept).
>
> I don't see a scenario where you could dispatch on an invisible primitive
> operation. First you must get into a context where you would have a view 
> of
> your type having that operation. This context cannot exist without another
> context where the type gets derived. In that context you must have
> overridden the operation. Where is a problem? Is it related to MI? [But 
> Ada
> does not respect privacy, when it checks inherited stuff, it does this as
> if in a full view of the type, which is another language bug, but still no
> problem.]

This seeems confused, and you ask the right question later...

>> I realize that you hate redispatching (a point that I tend to agree with 
>> you
>> on), but it's possible, and it's needed some part of the time (maybe 10% 
>> or
>> even less, but more than 0%), so it exists and has to be taken into 
>> account.
>
> But even if you convert to the class-wide you don't get visibility of the
> operation. In the scenario:
>
>   type T3 is new T1 with private;
> private
>   type T3 is new T2 with null record; -- Legal!
>
> a public client could not convert a T3 object to T2'Class. Could it?

No, but a private client can, and if you have a public type T4 derived from 
T3, it would not have the function operation.

package P2 is
   type T3 is new T1 with private;
   procedure Do_It (X : inT3);
private
   type T3 is new T2 with null record; -- Legal!
end P2;

with P2;
package P3 is
   type T4 is new P2.T3 with C : Character; end record; -- No defined F 
here.
end P3;

with P2, P3;
procedure Main is
   Obj : P3.T4;
begin
   Obj.Do_It; -- Calls Do_It with a T4 operation, does not have F.
end Main;

package body P2 is
   procedure Do_It (X : in T3) is
   begin
       if T2'Class(X) = F then -- Dispatching call to F, tag is T4, but 
there is no F for T4. Ouch.
           ...
       end if;
   end Do_It;
end P2;

>>>> have the feature at all (which is where I would stand).
>>>
>>> I don't see connection to anonymous access types, the rule applies to
>>> tagged results as well:
>>>
>>> package P1 is
>>>   type T1 is tagged null record;
>>>   type T2 is new T1 with null record;
>>>   function Foo return T2;
>>> end P1;
>>>
>>> with P1; use P1;
>>> package P2 is
>>>   type T3 is new T1 with private;
>>> private
>>>   type T3 is new T2 with null record; -- Legal!
>>
>> This is only legal because of a hack, which I was very much against
>> introducing. If you have an extension component, this is illegal:
>>
>>     type T4 is new T2 with record C : Character := '1'; end record; --
>> Illegal!!!
>
> Yes, the hack you mean is contravariance of an out argument or result 
> based
> on a guess about the type implementation (null extension). It is wrong 
> from
> the strong typing POV.
>
>>> end P2;
>>
>> I have tried to find a way to avoid this maintenance hazard (it's 
>> especially
>> bad for mix-in generics), but I haven't gotten any traction to date. We
>> could (if all of the extension components have defaults) automatically do
>> this as we do for null record, but the problem is that making overriding
>> required often detects bugs (failure to create a proper overriding). Plus
>> the problem of incompatibility (only in obscure cases).
>
> No. I know you don't believe in science and proofs but still, 
> conravariance
> in outputs is just wrong (under type extension).
>
> Instead of ugly hacks we better have had some delegation/body-composition
> methods at the declaration place to be able to tell that the overriding is
> basically the parent's implementation. We already allowed such stuff, e.g.
>
>   procedure Foo (...) is null;
>
> We have ugly executable precondition code at the declaration side. Why not
> to allow this for functions?

I don't understand what you mean. An expression function can be given as the 
overriding, but that doesn't help if you don't have the needed visibility to 
see the components in question (an aggregate is only legal if no private 
types are involved -- we tried to find a way to relax that for Ada 2005, but 
it just got way too messy).

>>> with P1; use P1;
>>> package P2 is
>>>   type T3 is new T1 with private;
>>> private
>>>   type T3 is new T2 with null record;
>>>   overriding function Foo return T3; -- ILLEGAL!
>>> end P2;
>>>
>>> As such the rule does not make any sense. You shall under no 
>>> circumstance
>>> prohibit overriding of inherited operations.
>>
>> That's only possible if you prohibit any extensions of T3. (Otherwise, 
>> you
>> get the dispatching problems that I noted previously, or you have to 
>> break
>> privacy by making the derived type illegal for something that is not
>> visible.) We've talked a bit about having such an aspect, but it is 
>> messy.
>
> Could you provide an example of dispatching problems you have in mind?

Done, see above.

>> To summarize: it's a bad interaction between privacy and things that 
>> require
>> overriding (abstract subprograms follow the same rules for the same
>> reasons). There's no real solution, else you could call abstract
>> subprograms -- and then what??
>
> Honestly I never understood how that could happen. The dispatching table
> must be defined for any non-abstract instance. This is statically 
> enforced,
> isn't it?

Right -- that's why you get the rule requiring visible operations. 
Statically enforcing it otherwise would require breaking privacy, which we 
won't do (outside of representation clauses, for which privacy doesn't make 
any sense anyway).

                            Randy. 




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

* Re: Ada design bug or GNAT bug?
  2015-07-03 17:33             ` Randy Brukardt
@ 2015-07-03 21:34               ` Dmitry A. Kazakov
  2015-07-04  3:11                 ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-07-03 21:34 UTC (permalink / raw)


On Fri, 3 Jul 2015 12:33:07 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 

>> But even if you convert to the class-wide you don't get visibility of the
>> operation. In the scenario:
>>
>>   type T3 is new T1 with private;
>> private
>>   type T3 is new T2 with null record; -- Legal!
>>
>> a public client could not convert a T3 object to T2'Class. Could it?
> 
> No, but a private client can, and if you have a public type T4 derived from 
> T3, it would not have the function operation.
> 
> package P2 is
>    type T3 is new T1 with private;
>    procedure Do_It (X : inT3);
> private
>    type T3 is new T2 with null record; -- Legal!
> end P2;
> 
> with P2;
> package P3 is
>    type T4 is new P2.T3 with C : Character; end record; -- No defined F here.

This must be illegal. The compiler shall require (unless T4 is abstract):

1. That the private part of the package had a full view of P2.T3

2. F overridden there.

E.g.

package P2.P3 is
   type T4 is new T3 with record
      C : Character;
   end record;
private
   overriding function F (...) return T4;
end P2.P3;

>> We have ugly executable precondition code at the declaration side. Why not
>> to allow this for functions?
> 
> I don't understand what you mean. An expression function can be given as the 
> overriding, but that doesn't help if you don't have the needed visibility to 
> see the components in question (an aggregate is only legal if no private 
> types are involved -- we tried to find a way to relax that for Ada 2005, but 
> it just got way too messy).

That is the idea, to do it without visibility. When you inherit bodies of
procedures you don't need visibility. You "convert" parameters (view
conversion, does nothing) and call the parent's body.

Similarly we could compose a body of an invisible operation. In the example
above the invisible operation is F, when we derive T4 from T3 above. We do
not need to know if F exists in order to say something like: if there is
any primitive function returning T3 override it by adding 'A' for the
component C. That would make

package P3 is
   type T4 is new T3 with record
      C : Character;
   end record
      with overriding function C => 'A';
          -- Imaginary syntax for automated function overriding aspect

We could allow formal parameters of the aspect to be matched against
parameters of overridden functions and used in the aggregate. We could
allow a name of a body to initialize the type extension instead of an
aggregate in order to move the mess into the package body instead of
exposing it in the declaration scope, etc.

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

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

* Re: Ada design bug or GNAT bug?
  2015-07-02 22:06           ` Randy Brukardt
@ 2015-07-04  1:52             ` Shark8
  2015-07-04  3:24               ` Randy Brukardt
  2015-07-04  7:46               ` Simon Wright
  2015-07-06 12:37             ` Vincent
  1 sibling, 2 replies; 46+ messages in thread
From: Shark8 @ 2015-07-04  1:52 UTC (permalink / raw)


On Thursday, July 2, 2015 at 6:04:50 PM UTC-6, Randy Brukardt wrote:
> 
> The reason Ada has anonymous access parameters was a desire (for Ada 9x) 
> that code from existing OOP languages like C++ could be directly converted 
> to Ada without having to think at all (thinking being necessary to get rid 
> of access types).

Do you think, in hindsight that (anonymous access parameters) was a mistake?

> [snip]
> >
> >One may think that the distinction between class type and tagged type is 
> >subtle, but the
> >implications of it are huge : without class object one needs as replacement 
> >access to a
> >class wide type. This has led to the use of access values everywhere when 
> >doing OOP.
> >To ease the pain access parameters and anonymous access types were 
> >introduced...
> 
> This seems to me to be nonsense. There's no need to use access types in Ada 
> OOP interfaces; "in out T" and "access T" have virtually the same semantics 
> when T is a tagged type. (Claw only has one access type in its entire 
> interface, used for a return type that ought to be by reference. Everything 
> else does not use visible access types.) It's more work this way, but it's 
> definitely possible.

I think I remember getting an error-message in GNAT awhile back about return and reference semantics... wasn't that something that Ada95 had but was later forbidden in Ada 2005? -- Also, do you think it would have been better to have extended-return signal to the compiler a desire for a build-in-place return-object?

Also, I seem to recall your dislike of INTERFACEs -- in hindsight, what would you have done differently if you needed the mechanism of "Type T has functions X, Y, and X" applied to a group of types? Generics, or some variations thereof?

>> with P1; use P1;
>> package P2 is
>>   type T3 is new T1 with private;
>> private
>>   type T3 is new T2 with null record; -- Legal!
>
>This is only legal because of a hack, which I was very much against
introducing. If you have an extension component, this is illegal:
>
>    type T4 is new T2 with record C : Character := '1'; end record; --  
Illegal!!!

Why is this hack required?/How was it justified? How would you address the problem w/o resorting to this hack?


Other than those specifics, I'm quite interested to know what you regard to be mistakes in Ada's design.


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

* Re: Ada design bug or GNAT bug?
  2015-07-03 21:34               ` Dmitry A. Kazakov
@ 2015-07-04  3:11                 ` Randy Brukardt
  2015-07-04 12:14                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2015-07-04  3:11 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:56pbwdnfce0k$.5et1apcv65k9.dlg@40tude.net...
> On Fri, 3 Jul 2015 12:33:07 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>
>>> But even if you convert to the class-wide you don't get visibility of 
>>> the
>>> operation. In the scenario:
>>>
>>>   type T3 is new T1 with private;
>>> private
>>>   type T3 is new T2 with null record; -- Legal!
>>>
>>> a public client could not convert a T3 object to T2'Class. Could it?
>>
>> No, but a private client can, and if you have a public type T4 derived 
>> from
>> T3, it would not have the function operation.
>>
>> package P2 is
>>    type T3 is new T1 with private;
>>    procedure Do_It (X : inT3);
>> private
>>    type T3 is new T2 with null record; -- Legal!
>> end P2;
>>
>> with P2;
>> package P3 is
>>    type T4 is new P2.T3 with C : Character; end record; -- No defined F 
>> here.
>
> This must be illegal. The compiler shall require (unless T4 is abstract):
>
> 1. That the private part of the package had a full view of P2.T3
>
> 2. F overridden there.

But of course that breaks privacy: T4 knows nothing about the full type of 
T3 or any private operations it may have. If you mean that such a derivation 
should *always* be illegal, well, perhaps that would have been better, but 
its clearly too late (it has been legal for 20+ years, there's plenty of 
code that depends on deriving from a non-visible private type -- Claw has a 
number of such types [from sibling inheritance]).

>>> We have ugly executable precondition code at the declaration side. Why 
>>> not
>>> to allow this for functions?
>>
>> I don't understand what you mean. An expression function can be given as 
>> the
>> overriding, but that doesn't help if you don't have the needed visibility 
>> to
>> see the components in question (an aggregate is only legal if no private
>> types are involved -- we tried to find a way to relax that for Ada 2005, 
>> but
>> it just got way too messy).
>
> That is the idea, to do it without visibility. When you inherit bodies of
> procedures you don't need visibility. You "convert" parameters (view
> conversion, does nothing) and call the parent's body.
>
> Similarly we could compose a body of an invisible operation. In the 
> example
> above the invisible operation is F, when we derive T4 from T3 above. We do
> not need to know if F exists in order to say something like: if there is
> any primitive function returning T3 override it by adding 'A' for the
> component C. That would make
>
> package P3 is
>   type T4 is new T3 with record
>      C : Character;
>   end record
>      with overriding function C => 'A';
>          -- Imaginary syntax for automated function overriding aspect
>
> We could allow formal parameters of the aspect to be matched against
> parameters of overridden functions and used in the aggregate. We could
> allow a name of a body to initialize the type extension instead of an
> aggregate in order to move the mess into the package body instead of
> exposing it in the declaration scope, etc.

I had suggested something on this line (but simpler): simply flag if using 
the default values of the extension components are enough for constructing 
such values (they often will be). But it didn't get much traction.

You could of course submit something like the above to Ada-Comment. (Make 
sure to include a good problem description if you do; the problem is usually 
more important than the suggested solution.) At the least, it would add 
weight to the existing problem.

                              Randy.





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

* Re: Ada design bug or GNAT bug?
  2015-07-04  1:52             ` Shark8
@ 2015-07-04  3:24               ` Randy Brukardt
  2015-07-04 11:02                 ` Build-in-place semantics? (Was: Ada design bug or GNAT bug?) Jacob Sparre Andersen
  2015-07-04 14:05                 ` Ada design bug or GNAT bug? Bob Duff
  2015-07-04  7:46               ` Simon Wright
  1 sibling, 2 replies; 46+ messages in thread
From: Randy Brukardt @ 2015-07-04  3:24 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:4228c0ea-837d-42a0-b2a8-a98d8d30f820@googlegroups.com...
On Thursday, July 2, 2015 at 6:04:50 PM UTC-6, Randy Brukardt wrote:
>>
>> The reason Ada has anonymous access parameters was a desire (for Ada 9x)
>> that code from existing OOP languages like C++ could be directly 
>> converted
>> to Ada without having to think at all (thinking being necessary to get 
>> rid
>> of access types).
>
>Do you think, in hindsight that (anonymous access parameters) was a 
>mistake?

Surely. They were introduced mainly to solve two problems: the missing "in 
out" parameters for functions (and that they solved so imperfectly that Ada 
2012 allows "in out" parameters for functions), and to allow dispatching on 
access types (something I'm dubious was necessary in the first place - 
dispatching on .all works in virtually all cases that I've seen). Plus they 
have weird dynamic accessibility semantics, which provides a tripping hazard 
(as Bob Duff would call it) -- an exception but only in unusual cases -- and 
a performance drain. "in out" has essentially the same semantics put without 
the hazard or performance issue.

...
>I think I remember getting an error-message in GNAT awhile back
>about return and reference semantics... wasn't that something that Ada95
>had but was later forbidden in Ada 2005?

Because it was near-nonsense; you had to return a global variable -- but you 
should be avoiding global variables as much as possible, not requiring them. 
They had a few uses, but not enough to preserve.

> -- Also, do you think it would have been better to have extended-return
> signal to the compiler a desire for a build-in-place return-object?

Probably not, build-in-place semantics isn't practical for all non-limited 
types (think normal assignment, can't build-in-place because if an exception 
occurs the original value has to be intact).

> Also, I seem to recall your dislike of INTERFACEs -- in hindsight, what
> would you have done differently if you needed the mechanism of
> "Type T has functions X, Y, and X" applied to a group of types?
> Generics, or some variations thereof?

I wouldn't need such a mechanism. :-) I'm dubious of the value of that in 
the first place -- it's not zero, but it's close enough that it isn't worth 
hairing up a language or implementation to get it.

>>> with P1; use P1;
>>> package P2 is
>>>   type T3 is new T1 with private;
>> private
>>>   type T3 is new T2 with null record; -- Legal!
>>
>>This is only legal because of a hack, which I was very much against
>>introducing. If you have an extension component, this is illegal:
>>
>>    type T4 is new T2 with record C : Character := '1'; end record; --  
>> Illegal!!!

>Why is this hack required?/How was it justified? How would you address the 
>problem w/o resorting to this hack?

The thread that Dmitry and I have been having answers this question, and I 
don't want to spend time to repeat it.

>Other than those specifics, I'm quite interested to know what you regard to 
>be mistakes in Ada's design.

Someday I'm going to write a paper/blog post on that. But not today. I'd 
like to accomplish some work at some point in the month of July. :-)

                        Randy.


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

* Re: Ada design bug or GNAT bug?
  2015-07-04  1:52             ` Shark8
  2015-07-04  3:24               ` Randy Brukardt
@ 2015-07-04  7:46               ` Simon Wright
  2015-07-04 12:00                 ` Björn Lundin
  1 sibling, 1 reply; 46+ messages in thread
From: Simon Wright @ 2015-07-04  7:46 UTC (permalink / raw)


Shark8 <onewingedshark@gmail.com> writes:

> Also, I seem to recall your dislike of INTERFACEs -- in hindsight,
> what would you have done differently if you needed the mechanism of
> "Type T has functions X, Y, and X" applied to a group of types?
> Generics, or some variations thereof?

Generic signature packages?

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

* Build-in-place semantics?  (Was: Ada design bug or GNAT bug?)
  2015-07-04  3:24               ` Randy Brukardt
@ 2015-07-04 11:02                 ` Jacob Sparre Andersen
  2015-07-04 12:15                   ` Dmitry A. Kazakov
  2015-07-05  0:40                   ` Randy Brukardt
  2015-07-04 14:05                 ` Ada design bug or GNAT bug? Bob Duff
  1 sibling, 2 replies; 46+ messages in thread
From: Jacob Sparre Andersen @ 2015-07-04 11:02 UTC (permalink / raw)


Randy Brukardt wrote:

> Probably not, build-in-place semantics isn't practical for all
> non-limited types (think normal assignment, can't build-in-place
> because if an exception occurs the original value has to be intact).

A very sensible requirement, but wouldn't it be nice ...

I suppose that compilers are allowed to use build-in-place when
initialising non-limited objects?  (But that would of course in practice
mean that you had two different compiled versions of every function.)

Greetings,

Jacob
-- 
»Saving keystrokes is the job of the text editor, not the
 programming language.«                    -- Preben Randhol

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

* Re: Ada design bug or GNAT bug?
  2015-07-04  7:46               ` Simon Wright
@ 2015-07-04 12:00                 ` Björn Lundin
  2015-07-05  0:48                   ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Björn Lundin @ 2015-07-04 12:00 UTC (permalink / raw)


On 2015-07-04 09:46, Simon Wright wrote:
> Shark8 <onewingedshark@gmail.com> writes:
> 
>> Also, I seem to recall your dislike of INTERFACEs -- in hindsight,
>> what would you have done differently if you needed the mechanism of
>> "Type T has functions X, Y, and X" applied to a group of types?
>> Generics, or some variations thereof?
> 
> Generic signature packages?
> 

I had this problem when implementing another companies proprietary
communications protocol, that we needed to communicate with.
The physical devices were picking-robots.
All messages had a common headers and then message specific fields.
And they had to have certain functions. To_String, Save_to_Database,
Send, etc.

Since I had complete control over the implementation, I
ended up using inheritance from an abstract type.

Some functions of the abstract type were implemented,
and others - to specialized for the inherited type -
was declared abstract.


--
Björn


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

* Re: Ada design bug or GNAT bug?
  2015-07-04  3:11                 ` Randy Brukardt
@ 2015-07-04 12:14                   ` Dmitry A. Kazakov
  2015-07-05  0:53                     ` Randy Brukardt
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-07-04 12:14 UTC (permalink / raw)


On Fri, 3 Jul 2015 22:11:18 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:56pbwdnfce0k$.5et1apcv65k9.dlg@40tude.net...
>> On Fri, 3 Jul 2015 12:33:07 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>
>>>> But even if you convert to the class-wide you don't get visibility of 
>>>> the
>>>> operation. In the scenario:
>>>>
>>>>   type T3 is new T1 with private;
>>>> private
>>>>   type T3 is new T2 with null record; -- Legal!
>>>>
>>>> a public client could not convert a T3 object to T2'Class. Could it?
>>>
>>> No, but a private client can, and if you have a public type T4 derived 
>>> from
>>> T3, it would not have the function operation.
>>>
>>> package P2 is
>>>    type T3 is new T1 with private;
>>>    procedure Do_It (X : inT3);
>>> private
>>>    type T3 is new T2 with null record; -- Legal!
>>> end P2;
>>>
>>> with P2;
>>> package P3 is
>>>    type T4 is new P2.T3 with C : Character; end record; -- No defined F 
>>> here.
>>
>> This must be illegal. The compiler shall require (unless T4 is abstract):
>>
>> 1. That the private part of the package had a full view of P2.T3
>>
>> 2. F overridden there.
> 
> But of course that breaks privacy: T4 knows nothing about the full type of 
> T3 or any private operations it may have.

There are a lot of other cases where you effectively unable to derive from
a type. Since they are not counted privacy breach, this one shouldn't
either.

In my view the problem is not in T4 but in T3, like in all other cases when
you would not be able to derive later. So my solution would be a mandatory
declaration of the public view as final. E.g.

package P2 is
   type T3 is new T1 with private; -- Illegal, no derived types possible
private
   type T3 is new T2 with null record;
end P2;

package P2 is
   type T3 is new T1 with private
       with Childless => True; -- Legal, this is the last public descendant
private
   type T3 is new T2 with null record;
end P2;

Now, T4 cannot claim knowing nothing.

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


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

* Re: Build-in-place semantics?  (Was: Ada design bug or GNAT bug?)
  2015-07-04 11:02                 ` Build-in-place semantics? (Was: Ada design bug or GNAT bug?) Jacob Sparre Andersen
@ 2015-07-04 12:15                   ` Dmitry A. Kazakov
  2015-07-05  0:45                     ` Randy Brukardt
  2015-07-05  0:40                   ` Randy Brukardt
  1 sibling, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-07-04 12:15 UTC (permalink / raw)


On Sat, 04 Jul 2015 13:02:26 +0200, Jacob Sparre Andersen wrote:

> Randy Brukardt wrote:
> 
>> Probably not, build-in-place semantics isn't practical for all
>> non-limited types (think normal assignment, can't build-in-place
>> because if an exception occurs the original value has to be intact).
> 
> A very sensible requirement, but wouldn't it be nice ...

In my view it is not.

Assignment is a syntax sugar of a primitive operation.

If an operation propagates an exception there is no obligation on mutable
parameters except than type invariants (and post-conditions bound to the
exception).

Compare it to a procedure with an in-out parameter.

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

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

* Re: Ada design bug or GNAT bug?
  2015-07-04  3:24               ` Randy Brukardt
  2015-07-04 11:02                 ` Build-in-place semantics? (Was: Ada design bug or GNAT bug?) Jacob Sparre Andersen
@ 2015-07-04 14:05                 ` Bob Duff
  1 sibling, 0 replies; 46+ messages in thread
From: Bob Duff @ 2015-07-04 14:05 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> Surely. They were introduced mainly to solve two problems: the missing "in 
> out" parameters for functions (and that they solved so imperfectly that Ada 
> 2012 allows "in out" parameters for functions), and to allow dispatching on 
> access types (something I'm dubious was necessary in the first place - 
> dispatching on .all works in virtually all cases that I've seen). 

Yes, but I wish the dereference operator wasn't so big and ugly,
not to mention illogical.  I like Pascal's "X^".  Then I'd disallow
implicit dereference.

>...Plus they 
> have weird dynamic accessibility semantics, which provides a tripping hazard 
> (as Bob Duff would call it)

I didn't invent the term "tripping hazard".  See here:

https://www.google.com/search?q=tripping+hazard&client=ubuntu&hs=3p4&channel=fs&tbm=isch&imgil=SxoKW-zTjNggSM%253A%253Br37mO7FI_EoFRM%253Bhttp%25253A%25252F%25252Fblog.poolcenter.com%25252Farticle.aspx%25253Farticleid%2525253D6055&source=iu&pf=m&fir=SxoKW-zTjNggSM%253A%252Cr37mO7FI_EoFRM%252C_&biw=1855&bih=1105&usg=__-Q2E2qE_rVvTQOoxftNipyTyDkc%3D&ved=0CCoQyjc&ei=It-XVcm_Jce2sAXEl6mwDg#imgrc=SxoKW-zTjNggSM%3A&usg=__-Q2E2qE_rVvTQOoxftNipyTyDkc%3D

One problem with those run-time accessibility checks is that there's
no contract -- it's not clear whether the caller or the callee is
supposed to ensure the check doesn't fail.  The rules about by-copy
vs. by-reference parameter passing have the same problem: When
parameter passing might be by reference, is the caller supposed to
avoid passing overlapping objects?  Or is the callee supposed to
avoid writing-then-reading that would cause trouble when overlapped?
The language doesn't say.

Most checks aren't like that.  E.g. callers should ensure that
preconditions are true, and callees should ensure that postconditions
are true.

Anonymous types would be OK if they didn't have special semantics --
they should just be a shorthand.  And it's really weird that Ada 83
allowed some kinds of anonymous types (task, array) but not others
(integer, record, ...).  (Consistency?)  And the array case has
weird semantics.

>... -- an exception but only in unusual cases -- and 
> a performance drain. "in out" has essentially the same semantics put without 
> the hazard or performance issue.

Pretty much.

> ...
>>I think I remember getting an error-message in GNAT awhile back
>>about return and reference semantics... wasn't that something that Ada95
>>had but was later forbidden in Ada 2005?
>
> Because it was near-nonsense; you had to return a global variable -- but you 
> should be avoiding global variables as much as possible, not requiring them. 
> They had a few uses, but not enough to preserve.

Yes, return by reference was a big mistake.  The intention was to
correct the mistake in Ada 83:

    function F return Some_Task is
        Local_Task : Some_Task;
    begin
        ...
        return Local_Task;

which is an utterly useless thing to do.  Build-in-place is a good
idea -- too bad we didn't think of that 10 years sooner.

>> -- Also, do you think it would have been better to have extended-return
>> signal to the compiler a desire for a build-in-place return-object?
>
> Probably not, build-in-place semantics isn't practical for all non-limited 
> types (think normal assignment, can't build-in-place because if an exception 
> occurs the original value has to be intact).

Ada pretends to support a compilation model where the compiler doesn't
have to look at bodies when compiling clients.  And the caller must know
whether the callee is build-in-place.  So triggering that via extended
return wouldn't work.

I say "pretends", because of generics and inlines.  Randy's compiler
manages to compile generic instantiations without looking at the body,
but that requires heroics.  A better language design would make that
implementation natural (with the macro-expansion model being just
an optimization).

A compilation model with such a glaring exception isn't much use,
IMHO, but I think ARG would like to keep up the pretense.  (Generics
are the glaring exception.  Inlines don't bother me, because that's
an optimization, and I can think of all sorts of optimizations that
require looking at bodies.  These days, gcc can do link-time
optimizations.)

>>Other than those specifics, I'm quite interested to know what you regard to 
>>be mistakes in Ada's design.
>
> Someday I'm going to write a paper/blog post on that. But not today. I'd 
> like to accomplish some work at some point in the month of July. :-)

I could write a book on that.  But Ada is still a much better design
than many other languages I could name!

- Bob


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

* Re: Build-in-place semantics?  (Was: Ada design bug or GNAT bug?)
  2015-07-04 11:02                 ` Build-in-place semantics? (Was: Ada design bug or GNAT bug?) Jacob Sparre Andersen
  2015-07-04 12:15                   ` Dmitry A. Kazakov
@ 2015-07-05  0:40                   ` Randy Brukardt
  1 sibling, 0 replies; 46+ messages in thread
From: Randy Brukardt @ 2015-07-05  0:40 UTC (permalink / raw)


Jacob Sparre Andersen" <sparre@nbi.dk> wrote in message 
news:87bnfsfanx.fsf_-_@adaheads.sparre-andersen.dk...
> Randy Brukardt wrote:
>
>> Probably not, build-in-place semantics isn't practical for all
>> non-limited types (think normal assignment, can't build-in-place
>> because if an exception occurs the original value has to be intact).
>
> A very sensible requirement, but wouldn't it be nice ...
>
> I suppose that compilers are allowed to use build-in-place when
> initialising non-limited objects?  (But that would of course in practice
> mean that you had two different compiled versions of every function.)

Yes, of course. It's not possible to write a program that can tell the 
difference. (Code inspection could tell, of course, but that's considered 
cheating - any code that gives the required semantics should be OK.)

One could avoid the assignment problem by introducing a temporary in just 
such cases, but that's essentially the same as not using build-in-place in 
the first place. One also could arrange to just use build-in-place for types 
that don't have the exception-on-assignment possibility (there are plenty of 
those).

                             Randy.


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

* Re: Build-in-place semantics?  (Was: Ada design bug or GNAT bug?)
  2015-07-04 12:15                   ` Dmitry A. Kazakov
@ 2015-07-05  0:45                     ` Randy Brukardt
  2015-07-05  7:10                       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Randy Brukardt @ 2015-07-05  0:45 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:xtm95y6tqdo6$.1tfgl96oattey$.dlg@40tude.net...
> On Sat, 04 Jul 2015 13:02:26 +0200, Jacob Sparre Andersen wrote:
>
>> Randy Brukardt wrote:
>>
>>> Probably not, build-in-place semantics isn't practical for all
>>> non-limited types (think normal assignment, can't build-in-place
>>> because if an exception occurs the original value has to be intact).
>>
>> A very sensible requirement, but wouldn't it be nice ...
>
> In my view it is not.
>
> Assignment is a syntax sugar of a primitive operation.
>
> If an operation propagates an exception there is no obligation on mutable
> parameters except than type invariants (and post-conditions bound to the
> exception).
>
> Compare it to a procedure with an in-out parameter.

A procedure with an in-out parameter shouldn't clobber the parameters on an 
exception, either. (Consider what happens for a by-copy parameter, of any 
mode, when an exception is raised.) By-reference parameter passing 
introduces the problem, and one could easily argue that it is the bug in the 
language design (introduced for efficiency), not the difference in 
requirements for assignment.

Also note that no parameter will be partially modified by a procedure unless 
the procedure is actually written to do that. That's under the control of 
the programmer. If the language allowed clobbering part of an object during 
a failed assignment, no recovery would be possible (the object would be 
"abnormal" and could never be used again until it is reinitialized -- that's 
what happens for abort). That would make a lot of things hard to guarantee 
short of using SPARK to prove exception absence.

                     Randy.




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

* Re: Ada design bug or GNAT bug?
  2015-07-04 12:00                 ` Björn Lundin
@ 2015-07-05  0:48                   ` Randy Brukardt
  0 siblings, 0 replies; 46+ messages in thread
From: Randy Brukardt @ 2015-07-05  0:48 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1436 bytes --]

"Björn Lundin" <b.f.lundin@gmail.com> wrote in message 
news:mn8hok$fdf$1@dont-email.me...
> On 2015-07-04 09:46, Simon Wright wrote:
>> Shark8 <onewingedshark@gmail.com> writes:
>>
>>> Also, I seem to recall your dislike of INTERFACEs -- in hindsight,
>>> what would you have done differently if you needed the mechanism of
>>> "Type T has functions X, Y, and X" applied to a group of types?
>>> Generics, or some variations thereof?
>>
>> Generic signature packages?
>>
>
> I had this problem when implementing another companies proprietary
> communications protocol, that we needed to communicate with.
> The physical devices were picking-robots.
> All messages had a common headers and then message specific fields.
> And they had to have certain functions. To_String, Save_to_Database,
> Send, etc.
>
> Since I had complete control over the implementation, I
> ended up using inheritance from an abstract type.
>
> Some functions of the abstract type were implemented,
> and others - to specialized for the inherited type -
> was declared abstract.

Right, with single inheritance. Good enough for 98% of problems, IMHO. I've 
used abstract types this way (in Claw and in Claw tools), but I found that 
the main gain was the shared implementations that could be provided by the 
abstract type. Interfaces don't allow them, so they provide cool-looking, 
but mainly useless capabilities.

                                 Randy.




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

* Re: Ada design bug or GNAT bug?
  2015-07-04 12:14                   ` Dmitry A. Kazakov
@ 2015-07-05  0:53                     ` Randy Brukardt
  0 siblings, 0 replies; 46+ messages in thread
From: Randy Brukardt @ 2015-07-05  0:53 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1myo335gjwyy3$.1bthq0cugahll.dlg@40tude.net...
> On Fri, 3 Jul 2015 22:11:18 -0500, Randy Brukardt wrote:
...
>> But of course that breaks privacy: T4 knows nothing about the full type 
>> of
>> T3 or any private operations it may have.
>
> There are a lot of other cases where you effectively unable to derive from
> a type. Since they are not counted privacy breach, this one shouldn't
> either.

There are? I can't think of any. Ada 95 had an accessibility check, but 
that's gone in more recent versions of the language.

Of course, I hardly ever use derived types other than for extension. Like 
interfaces, the other uses come up so rarely that they aren't worth worrying 
about. So I may have just forgotten something.

> In my view the problem is not in T4 but in T3, like in all other cases 
> when
> you would not be able to derive later. So my solution would be a mandatory
> declaration of the public view as final. E.g.
>
> package P2 is
>   type T3 is new T1 with private; -- Illegal, no derived types possible
> private
>   type T3 is new T2 with null record;
> end P2;
>
> package P2 is
>   type T3 is new T1 with private
>       with Childless => True; -- Legal, this is the last public descendant
> private
>   type T3 is new T2 with null record;
> end P2;
>
> Now, T4 cannot claim knowing nothing.

Fine idea for Ada 9x, but way too late nowdays. We're not going to break 50% 
of the existing Ada code...

                                             Randy.


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

* Re: Build-in-place semantics?  (Was: Ada design bug or GNAT bug?)
  2015-07-05  0:45                     ` Randy Brukardt
@ 2015-07-05  7:10                       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-07-05  7:10 UTC (permalink / raw)


On Sat, 4 Jul 2015 19:45:39 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:xtm95y6tqdo6$.1tfgl96oattey$.dlg@40tude.net...
>> On Sat, 04 Jul 2015 13:02:26 +0200, Jacob Sparre Andersen wrote:
>>
>>> Randy Brukardt wrote:
>>>
>>>> Probably not, build-in-place semantics isn't practical for all
>>>> non-limited types (think normal assignment, can't build-in-place
>>>> because if an exception occurs the original value has to be intact).
>>>
>>> A very sensible requirement, but wouldn't it be nice ...
>>
>> In my view it is not.
>>
>> Assignment is a syntax sugar of a primitive operation.
>>
>> If an operation propagates an exception there is no obligation on mutable
>> parameters except than type invariants (and post-conditions bound to the
>> exception).
>>
>> Compare it to a procedure with an in-out parameter.
> 
> A procedure with an in-out parameter shouldn't clobber the parameters on an 
> exception, either.

Yes. It must respect the type invariant.

> (Consider what happens for a by-copy parameter, of any 
> mode, when an exception is raised.) By-reference parameter passing 
> introduces the problem, and one could easily argue that it is the bug in the 
> language design (introduced for efficiency), not the difference in 
> requirements for assignment.

by-copy vs. by-reference is an implementation detail. The contract must
define the parameter state in the case of an exception. Since Ada lacks
exception contracts there is no way to do this.

But it is not the language's business define or imply such contracts.

> Also note that no parameter will be partially modified by a procedure unless 
> the procedure is actually written to do that. That's under the control of 
> the programmer. If the language allowed clobbering part of an object during 
> a failed assignment, no recovery would be possible (the object would be 
> "abnormal" and could never be used again until it is reinitialized -- that's 
> what happens for abort).

PL/1 exception model? No, recovery is easier if you do not rely on that.
You would just roll back the context until the latest safe state.

> That would make a lot of things hard to guarantee 
> short of using SPARK to prove exception absence.

It would make things easier if there were proper contracts on parameters of
all operations, assignment included.

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


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

* Re: Ada design bug or GNAT bug?
  2015-07-02 22:06           ` Randy Brukardt
  2015-07-04  1:52             ` Shark8
@ 2015-07-06 12:37             ` Vincent
  2015-07-06 20:05               ` Randy Brukardt
  2015-07-07  8:06               ` Dmitry A. Kazakov
  1 sibling, 2 replies; 46+ messages in thread
From: Vincent @ 2015-07-06 12:37 UTC (permalink / raw)


Le vendredi 3 juillet 2015 02:04:50 UTC+2, Randy Brukardt a écrit :

> The type Ichbiah wanted was syntactic sugar only. The semantics would have 
> been very similar to that of tagged types. The primary difference would have 
> been that we wouldn't have had to wait for Ada 2005 to get prefix calls.
> 
> [...]
> >One may think that the distinction between class type and tagged type is 
> >subtle, but the implications of it are huge : without class object one 
> >needs as replacement access to a class wide type. This has led to the use
> >of access values everywhere when doing OOP.
> >To ease the pain access parameters and anonymous access types were 
> >introduced...
> 
> This seems to me to be nonsense. There's no need to use access types in Ada 
> OOP interfaces; "in out T" and "access T" have virtually the same semantics 
> when T is a tagged type. (Claw only has one access type in its entire 
> interface, used for a return type that ought to be by reference. Everything 
> else does not use visible access types.) It's more work this way, but it's 
> definitely possible.

Yes it is possible, but it is more work, since one has to encapsulate the access
type into a "handle object". The pity is that this work is not done by the compiler, through a proper language defined mecanism. (This is what I think of when I speak of a "class type").

And even if you and I call it nonsense to use access types everywhere in case of
polymorphism, many textbooks present it as the normal Ada way of Advanced OOP.

Therefore I maintain that the "tagged type" concept of Ada 95 was, at least, incomplete, not to say awkward.

Regards,

Vincent

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

* Re: Ada design bug or GNAT bug?
  2015-07-06 12:37             ` Vincent
@ 2015-07-06 20:05               ` Randy Brukardt
  2015-07-07  8:06               ` Dmitry A. Kazakov
  1 sibling, 0 replies; 46+ messages in thread
From: Randy Brukardt @ 2015-07-06 20:05 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2413 bytes --]

"Vincent" <vincent.diemunsch@gmail.com> wrote in message 
news:701370ff-559b-458f-a107-793095a15749@googlegroups.com...
>Le vendredi 3 juillet 2015 02:04:50 UTC+2, Randy Brukardt a écrit :
>
>> This seems to me to be nonsense. There's no need to use access types in 
>> Ada
>> OOP interfaces; "in out T" and "access T" have virtually the same 
>> semantics
>> when T is a tagged type. (Claw only has one access type in its entire
>> interface, used for a return type that ought to be by reference. 
>> Everything
>> else does not use visible access types.) It's more work this way, but 
>> it's
>> definitely possible.
>
>Yes it is possible, but it is more work, since one has to encapsulate the 
>access
>type into a "handle object".

Access type? It depends on the problem, of course, but 90% of OOP objects 
need no access type, named that or anything else (handle, cursor, etc.). If 
you think you need one (of *any* sort), you probably are still confused by 
the C++/Java model. Claw (windowing interface for Windows) doesn't expose 
handles of any sort for windows and most of the other object types (I would 
have said all, but I'd don't recall the exact way the menus work). It only 
exposes objects of various types (windows/controls, canvases, menus, etc.)

>The pity is that this work is not done by the compiler, through a proper 
>language
>defined mecanism. (This is what I think of when I speak of a "class type").

Well, there's little point for there to be a language-defined mechanism for 
something that you don't even need. In addition, if one properly defines 
their OOP without using access types, then one can use the indefinite 
containers to provide handles in the event that some are needed. That's much 
better than raw access types, as memory management and (usually) dangling 
handle checking is included for free.

>And even if you and I call it nonsense to use access types everywhere in 
>case of
>polymorphism, many textbooks present it as the normal Ada way of Advanced 
>OOP.

Many textbooks? There aren't "many textbooks" for Ada in the first place. I 
only know of a handful that discuss Ada OOP.

> Therefore, I maintain that the "tagged type" concept of Ada 95 was, at 
> least,
> incomplete, not to say awkward.

Therefore, I maintain that you're still confused about how to use Ada OOP. 
That's OK, lots of others are as well. :-)

                                Randy.


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

* Re: Ada design bug or GNAT bug?
  2015-07-06 12:37             ` Vincent
  2015-07-06 20:05               ` Randy Brukardt
@ 2015-07-07  8:06               ` Dmitry A. Kazakov
  1 sibling, 0 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2015-07-07  8:06 UTC (permalink / raw)


On Mon, 6 Jul 2015 05:37:32 -0700 (PDT), Vincent wrote:

> Yes it is possible, but it is more work, since one has to encapsulate the access
> type into a "handle object".

It seems that you conflate by-reference semantics with access types. You
don't need access types to have referential semantics, and you don't need
referential semantics to have polymorphism. As I side note, I suppose that
confusion comes from the idea that an object may have many types. It is not
so in Ada and it is not so in any consistently typed system.

Most cases when you would need an access type in Ada are language design
bugs, which applies to all other languages as well.

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

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

end of thread, other threads:[~2015-07-07  8:06 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-20 18:55 Ada design bug or GNAT bug? Dmitry A. Kazakov
2015-06-21  2:42 ` Randy Brukardt
2015-06-21  6:47   ` Dmitry A. Kazakov
2015-06-22 17:39     ` Randy Brukardt
2015-06-22 18:16       ` Dmitry A. Kazakov
2015-06-23 11:00         ` G.B.
2015-06-23 14:27           ` Dmitry A. Kazakov
2015-06-23 11:45         ` G.B.
2015-06-23 14:30           ` Dmitry A. Kazakov
2015-07-02 22:22         ` Randy Brukardt
2015-07-03  8:02           ` Dmitry A. Kazakov
2015-07-03 17:33             ` Randy Brukardt
2015-07-03 21:34               ` Dmitry A. Kazakov
2015-07-04  3:11                 ` Randy Brukardt
2015-07-04 12:14                   ` Dmitry A. Kazakov
2015-07-05  0:53                     ` Randy Brukardt
2015-06-22 18:27       ` Shark8
2015-06-23 11:51         ` vincent.diemunsch
2015-06-23 19:55           ` Shark8
2015-06-23 13:06         ` vincent.diemunsch
2015-06-23 14:30           ` David Botton
2015-06-23 15:57             ` Niklas Holsti
2015-06-23 16:01               ` G.B.
2015-06-23 18:05               ` David Botton
2015-06-23 19:38               ` David Botton
2015-06-23 14:38           ` Dmitry A. Kazakov
2015-06-23 16:57             ` Vincent
2015-06-23 17:15               ` Dmitry A. Kazakov
2015-06-23 19:14                 ` vincent.diemunsch
2015-06-23 19:33                   ` Dmitry A. Kazakov
2015-06-23 17:42           ` Jeffrey R. Carter
2015-07-02 22:06           ` Randy Brukardt
2015-07-04  1:52             ` Shark8
2015-07-04  3:24               ` Randy Brukardt
2015-07-04 11:02                 ` Build-in-place semantics? (Was: Ada design bug or GNAT bug?) Jacob Sparre Andersen
2015-07-04 12:15                   ` Dmitry A. Kazakov
2015-07-05  0:45                     ` Randy Brukardt
2015-07-05  7:10                       ` Dmitry A. Kazakov
2015-07-05  0:40                   ` Randy Brukardt
2015-07-04 14:05                 ` Ada design bug or GNAT bug? Bob Duff
2015-07-04  7:46               ` Simon Wright
2015-07-04 12:00                 ` Björn Lundin
2015-07-05  0:48                   ` Randy Brukardt
2015-07-06 12:37             ` Vincent
2015-07-06 20:05               ` Randy Brukardt
2015-07-07  8:06               ` Dmitry A. Kazakov

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