comp.lang.ada
 help / color / mirror / Atom feed
* Is this expected behavior or not
@ 2013-03-11 19:42 Anh Vo
  2013-03-11 20:01 ` Robert A Duff
  0 siblings, 1 reply; 242+ messages in thread
From: Anh Vo @ 2013-03-11 19:42 UTC (permalink / raw)


I have read ARM section 3.2.4, Subtype Predicates, I did not see any rules prohibiting from using attribute 'Succ as contained in the code nipet below. I would expect Prime'Succ (3) return 5 for next prime number. However, 4 is returned instead. Is this a correct behavior?

pragma Assertion_Policy (Check);
with Ada.Text_Io;
with Ada.Exceptions; use Ada;

procedure Predicates_Test is
   use Text_Io;

   subtype Prime is Natural range 1 .. 1000
      with Dynamic_Predicate =>
      (case Prime is
         when 1 => False,
         when 2 => True,
         when others => Prime mod 2 /= 0 and then
                        (for all K in 3 .. Prime - 1 => Prime mod K /= 0));

   Current_Prime_Number : constant Natural := 3;
   Next_Prime_Number : constant Natural := 5;

begin
   Put_Line ("Predicates_Test starts");

   if Prime'Succ (Current_Prime_Number) = Next_Prime_Number then
      Put_Line ("The next prime number matches expectation");
   else
      Put_Line (Prime'Succ(Current_Prime_Number)'Img &
                                              " is not an expected number");
   end if;

   Put_Line ("Predicates_Test ends");
exception
   when Err : others =>
      Put_Line ("Houston we have a problem: " &
                                       Exceptions.Exception_Information(Err));
end Predicates_Test;




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

* Re: Is this expected behavior or not
  2013-03-11 19:42 Is this expected behavior or not Anh Vo
@ 2013-03-11 20:01 ` Robert A Duff
  2013-03-11 20:41   ` Shark8
                     ` (2 more replies)
  0 siblings, 3 replies; 242+ messages in thread
From: Robert A Duff @ 2013-03-11 20:01 UTC (permalink / raw)


Anh Vo <anhvofrcaus@gmail.com> writes:

> I have read ARM section 3.2.4, Subtype Predicates, I did not see any
> rules prohibiting from using attribute 'Succ as contained in the code
> nipet below. I would expect Prime'Succ (3) return 5 for next prime
> number. However, 4 is returned instead. Is this a correct behavior?

It is standard-conforming behavior.  Prime'Succ is the same as
Prime'Base'Succ.  Many other attributes behave the same way.
This has been true since Ada 83.  For example, Prime'Succ(1000) = 1001,
and does not raise an exception.  Positive'Image (-10) = "-10".

>    subtype Prime is Natural range 1 .. 1000

- Bob



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

* Re: Is this expected behavior or not
  2013-03-11 20:01 ` Robert A Duff
@ 2013-03-11 20:41   ` Shark8
  2013-03-12  9:27     ` Dmitry A. Kazakov
  2013-03-11 20:43   ` Anh Vo
  2013-03-12  9:17   ` Dmitry A. Kazakov
  2 siblings, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-11 20:41 UTC (permalink / raw)


On Monday, March 11, 2013 2:01:04 PM UTC-6, Robert A Duff wrote:
> Anh Vo <anhvofrcaus@gmail.com> writes:
> 
> > I have read ARM section 3.2.4, Subtype Predicates, I did not see any
> > rules prohibiting from using attribute 'Succ as contained in the code
> > nipet below. I would expect Prime'Succ (3) return 5 for next prime
> > number. However, 4 is returned instead. Is this a correct behavior?
> 
> It is standard-conforming behavior.  Prime'Succ is the same as
> Prime'Base'Succ.  Many other attributes behave the same way.
> This has been true since Ada 83.  For example, Prime'Succ(1000) = 1001,
> and does not raise an exception.

This is something that is especially useful: consider the instance where you are slicing out portions of an array, say parsing out a STRING:VALUE sort of construction or doing some [certain] linear combinations:

  Key : Constant String := Get_Part( Element, Before );
  Val : Constant String := Get_Part( Element, After  );
-- Where Get_Part is:
	Type Portion is ( Before, After );
	Function Get_Part(	Item : String;
				Part : Portion
			 )  Return String is
	    Use Ada.Strings.Fixed;
	    Pos : Constant Natural := Index(
					Source  => Item,
					Pattern => "" & Seperator
				      );

	    SubType Head is Positive Range Item'First..Integer'Pred(Pos);
	    SubType Tail is Positive Range Positive'Succ(Pos)..Item'Last;
	Begin
	    Return (if Part = Before then Item(Head) else Item(Tail));
	End Get_Part;

We don't want the subtype "Head" to fail when the Pred'(Pos) is applied [and Pos = 1] while declaring the range; this precisely because the null-range is valid and what we desire. The construction of range 1..0 should therefore not generate an exception despite 0 not being a member of Positive.



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

* Re: Is this expected behavior or not
  2013-03-11 20:01 ` Robert A Duff
  2013-03-11 20:41   ` Shark8
@ 2013-03-11 20:43   ` Anh Vo
  2013-03-11 22:32     ` Randy Brukardt
  2013-03-11 22:38     ` Robert A Duff
  2013-03-12  9:17   ` Dmitry A. Kazakov
  2 siblings, 2 replies; 242+ messages in thread
From: Anh Vo @ 2013-03-11 20:43 UTC (permalink / raw)


On Monday, March 11, 2013 1:01:04 PM UTC-7, Robert A Duff wrote:
>> Anh Vo <anhvofrcaus@gmail.com> writes: 
>> I have read ARM section 3.2.4, Subtype Predicates, I did not see any 
>> rules prohibiting from using attribute 'Succ as contained in the code 
>> nipet below. I would expect Prime'Succ (3) return 5 for next prime 
>> number. However, 4 is returned instead. Is this a correct behavior? 

>It is standard-conforming behavior. Prime'Succ is the same as Prime'Base'Succ. >Many other attributes behave the same way. This has been true since Ada 83. >For example, Prime'Succ(1000) = 1001, and does not raise an exception. >Positive'Image (-10) = "-10". 

Thank you for your clarification. My next question is that should ARM mention some thing of that effect regarding subtype predicates.






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

* Re: Is this expected behavior or not
  2013-03-11 20:43   ` Anh Vo
@ 2013-03-11 22:32     ` Randy Brukardt
  2013-03-11 22:38     ` Robert A Duff
  1 sibling, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-03-11 22:32 UTC (permalink / raw)


"Anh Vo" <anhvofrcaus@gmail.com> wrote in message 
news:ec2783d9-1ae6-419e-97ad-12cb9e6c3d74@googlegroups.com...
>On Monday, March 11, 2013 1:01:04 PM UTC-7, Robert A Duff wrote:
>>> Anh Vo <anhvofrcaus@gmail.com> writes:
>>> I have read ARM section 3.2.4, Subtype Predicates, I did not see any
>>> rules prohibiting from using attribute 'Succ as contained in the code
>>> nipet below. I would expect Prime'Succ (3) return 5 for next prime
>>> number. However, 4 is returned instead. Is this a correct behavior?
>
>>It is standard-conforming behavior. Prime'Succ is the same as 
>>Prime'Base'Succ.
>>Many other attributes behave the same way. This has been true since Ada 
>>83.
>>For example, Prime'Succ(1000) = 1001, and does not raise an exception.
>>Positive'Image (-10) = "-10".
>
>Thank you for your clarification. My next question is that should ARM 
>mention
>some thing of that effect regarding subtype predicates.

It seems unnecessary, because the behavior is the same as that for 
constraints. Usually, we only talk specifically about predicates when their 
behavior is different than constraints -- otherwise we'd be repeating dozens 
of "obvious" notes. And of course the Standard is not a tutorial for the 
language.

One could argue that 'Pred and 'Succ should have been illegal (like 'First 
and 'Last are), but it's too late to do that. The reason that 'First and 
'Last are illegal is because of potential confusion about the meaning. The 
same is true here - but the effect is less (it's the same as constraints), 
so its a marginal case in any event.

                                            Randy.

P.S. I'm surprised anyone uses those attributes: I almost never do. Now, if 
we had implemented the procedure version that we talked about briefly, that 
would have gotten plenty of use.








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

* Re: Is this expected behavior or not
  2013-03-11 20:43   ` Anh Vo
  2013-03-11 22:32     ` Randy Brukardt
@ 2013-03-11 22:38     ` Robert A Duff
  1 sibling, 0 replies; 242+ messages in thread
From: Robert A Duff @ 2013-03-11 22:38 UTC (permalink / raw)


(Sorry, I didn't mean to send email.)

Anh Vo <anhvofrcaus@gmail.com> writes:

> Thank you for your clarification.

You're welcome.

>...My next question is that should ARM
> mention some thing of that effect regarding subtype predicates.

It's not necessary.  The description of S'Succ makes it clear that it
applies to S'Base, and returns S'Base.  And it says somewhere that the
predicate of a base subtype is True.  And that the values of a subtype
don't care about predicates anyway.

Potentially confusing, perhaps, but I think it's correct.

Now an Ada textbook, on the other hand ...

- Bob



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

* Re: Is this expected behavior or not
  2013-03-11 20:01 ` Robert A Duff
  2013-03-11 20:41   ` Shark8
  2013-03-11 20:43   ` Anh Vo
@ 2013-03-12  9:17   ` Dmitry A. Kazakov
  2013-03-13  0:10     ` Shark8
  2 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-12  9:17 UTC (permalink / raw)


On Mon, 11 Mar 2013 16:01:04 -0400, Robert A Duff wrote:

> Anh Vo <anhvofrcaus@gmail.com> writes:
> 
>> I have read ARM section 3.2.4, Subtype Predicates, I did not see any
>> rules prohibiting from using attribute 'Succ as contained in the code
>> nipet below. I would expect Prime'Succ (3) return 5 for next prime
>> number. However, 4 is returned instead. Is this a correct behavior?
> 
> It is standard-conforming behavior.  Prime'Succ is the same as
> Prime'Base'Succ.

Is the profile same? Let S be a subtype of T, then is 'Succ contravariant
in the result? E.g.

   function "'Succ" (X : S) return T'Base;

for any subtype. Or it is just an erroneous inheritance of the base
operation for fully covariant

   function "'Succ" (X : S) return S;

Or, maybe, it is not even covariant in the argument. Which might be the
case. Considering

   Prime'Succ (2)

If 'Succ is convariant in the argument, this shall raise Constraint_Error
because 2 is not Prime.

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



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

* Re: Is this expected behavior or not
  2013-03-11 20:41   ` Shark8
@ 2013-03-12  9:27     ` Dmitry A. Kazakov
  2013-03-12 17:19       ` Robert A Duff
  2013-03-12 23:14       ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-12  9:27 UTC (permalink / raw)


On Mon, 11 Mar 2013 13:41:43 -0700 (PDT), Shark8 wrote:

[...]
> We don't want the subtype "Head" to fail when the Pred'(Pos) is applied
> [and Pos = 1] while declaring the range; this precisely because the
> null-range is valid and what we desire. The construction of range 1..0
> should therefore not generate an exception despite 0 not being a member of
> Positive.

The issue of the bounds of an empty string is not related to subtypes. It
has a long history. But in short, you should not break one thing in order
to save another.

The semantics of 'Pred and 'Succ shall be properly defined in terms of
convariance of the argument and the result. There are arguments for and
against contravariant results. It goes straight to the circle-ellipse
controversy.

As Robert pointed out Ada tends to contravariance for numeric operations.
But it is not a trivial choice for 'Pred, 'Succ, 'Range. Consider

   for I in Prime'Range loop -- What is this supposed to mean?
      ...

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



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

* Re: Is this expected behavior or not
  2013-03-12  9:27     ` Dmitry A. Kazakov
@ 2013-03-12 17:19       ` Robert A Duff
  2013-03-12 17:42         ` Dmitry A. Kazakov
  2013-03-12 23:14       ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Robert A Duff @ 2013-03-12 17:19 UTC (permalink / raw)


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

> The semantics of 'Pred and 'Succ shall be properly defined in terms of
> convariance of the argument and the result. There are arguments for and
> against contravariant results. It goes straight to the circle-ellipse
> controversy.

The profile of 'Succ is given in RM-3.5(23):

    function S'Succ (Arg: S'Base) return S'Base;

It's neither contravariant nor covariant -- it's invariant.
One way to think of it is that S'Succ is just a shorthand
for S'Base'Succ.  I admit that's somewhat confusing,
but it's just like operator "+" -- there's no "+" specific
to Positive, nor is there 'Succ specific to Positive -- both
operate on Integer'Base, and don't do any range checking on
their parameters or result.

> As Robert pointed out Ada tends to contravariance for numeric operations.
> But it is not a trivial choice for 'Pred, 'Succ, 'Range. Consider
>
>    for I in Prime'Range loop -- What is this supposed to mean?
>       ...

It doesn't mean anything -- it's illegal.

- Bob



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

* Re: Is this expected behavior or not
  2013-03-12 17:19       ` Robert A Duff
@ 2013-03-12 17:42         ` Dmitry A. Kazakov
  2013-03-12 18:04           ` Georg Bauhaus
  2013-03-12 23:21           ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-12 17:42 UTC (permalink / raw)


On Tue, 12 Mar 2013 13:19:06 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> The semantics of 'Pred and 'Succ shall be properly defined in terms of
>> convariance of the argument and the result. There are arguments for and
>> against contravariant results. It goes straight to the circle-ellipse
>> controversy.
> 
> The profile of 'Succ is given in RM-3.5(23):
> 
>     function S'Succ (Arg: S'Base) return S'Base;
> 
> It's neither contravariant nor covariant -- it's invariant.

Invariant = contravariant.

>>    for I in Prime'Range loop -- What is this supposed to mean?
>>       ...
> 
> It doesn't mean anything -- it's illegal.

Why Prime'Succ is legal then?

And what about:

   for I in Prime'First..Prime'Last loop

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



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

* Re: Is this expected behavior or not
  2013-03-12 17:42         ` Dmitry A. Kazakov
@ 2013-03-12 18:04           ` Georg Bauhaus
  2013-03-12 18:21             ` Dmitry A. Kazakov
  2013-03-12 23:21           ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-12 18:04 UTC (permalink / raw)


On 12.03.13 18:42, Dmitry A. Kazakov wrote:
> On Tue, 12 Mar 2013 13:19:06 -0400, Robert A Duff wrote:
> 
>> > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> > 
>>> >> The semantics of 'Pred and 'Succ shall be properly defined in terms of
>>> >> convariance of the argument and the result. There are arguments for and
>>> >> against contravariant results. It goes straight to the circle-ellipse
>>> >> controversy.
>> > 
>> > The profile of 'Succ is given in RM-3.5(23):
>> > 
>> >     function S'Succ (Arg: S'Base) return S'Base;
>> > 
>> > It's neither contravariant nor covariant -- it's invariant.
> Invariant = contravariant.

In Ada? For non-tagged types?




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

* Re: Is this expected behavior or not
  2013-03-12 18:04           ` Georg Bauhaus
@ 2013-03-12 18:21             ` Dmitry A. Kazakov
  2013-03-12 22:23               ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-12 18:21 UTC (permalink / raw)


On Tue, 12 Mar 2013 19:04:31 +0100, Georg Bauhaus wrote:

> On 12.03.13 18:42, Dmitry A. Kazakov wrote:
>> On Tue, 12 Mar 2013 13:19:06 -0400, Robert A Duff wrote:
>> 
>>> > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>> > 
>>>> >> The semantics of 'Pred and 'Succ shall be properly defined in terms of
>>>> >> convariance of the argument and the result. There are arguments for and
>>>> >> against contravariant results. It goes straight to the circle-ellipse
>>>> >> controversy.
>>> > 
>>> > The profile of 'Succ is given in RM-3.5(23):
>>> > 
>>> >     function S'Succ (Arg: S'Base) return S'Base;
>>> > 
>>> > It's neither contravariant nor covariant -- it's invariant.
>> Invariant = contravariant.
> 
> In Ada? For non-tagged types?

Tagged is a special case, nothing more.

When the compiler allows instances of Prime in an operation of Prime'Base
that means that Prime inherits the operation <=> Prime is a subtype of
Prime'Base [in an interface having the operation]. In our case the
operation is 'Succ. Now if the argument, or result of 'Succ stays
Prime'Base that is the definition of the operation being contravariant in
it.

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



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

* Re: Is this expected behavior or not
  2013-03-12 18:21             ` Dmitry A. Kazakov
@ 2013-03-12 22:23               ` Georg Bauhaus
  2013-03-13  8:49                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-12 22:23 UTC (permalink / raw)


On 12.03.13 19:21, Dmitry A. Kazakov wrote:
> On Tue, 12 Mar 2013 19:04:31 +0100, Georg Bauhaus wrote:
>
>> On 12.03.13 18:42, Dmitry A. Kazakov wrote:
>>> On Tue, 12 Mar 2013 13:19:06 -0400, Robert A Duff wrote:

>>>>> The profile of 'Succ is given in RM-3.5(23):
>>>>>
>>>>>      function S'Succ (Arg: S'Base) return S'Base;
>>>>>
>>>>> It's neither contravariant nor covariant -- it's invariant.
>>> Invariant = contravariant.
>>
>> In Ada? For non-tagged types?
>
> Tagged is a special case, nothing more.
>
> When the compiler allows instances of Prime in an operation of Prime'Base
> that means that Prime inherits the operation

No inheritance involved here, in Ada, where the object involved simply is of
an unconstrained subtype of the given type of Prime, which is not Prime.
This type, not Prime (which isn't a type), has the attribute 'Succ, irrespective
of the subtype, and irrespective of some differently formalizing theory of types
that, I think, can only help to set things straight here if every word used
in every non-Ada argument gets a subscript indicating its frame of reference.






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

* Re: Is this expected behavior or not
  2013-03-12  9:27     ` Dmitry A. Kazakov
  2013-03-12 17:19       ` Robert A Duff
@ 2013-03-12 23:14       ` Randy Brukardt
  1 sibling, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-03-12 23:14 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:mtz6eyrgv524.r2yf3jw9vid3$.dlg@40tude.net...
> On Mon, 11 Mar 2013 13:41:43 -0700 (PDT), Shark8 wrote:
>
> [...]
>> We don't want the subtype "Head" to fail when the Pred'(Pos) is applied
>> [and Pos = 1] while declaring the range; this precisely because the
>> null-range is valid and what we desire. The construction of range 1..0
>> should therefore not generate an exception despite 0 not being a member 
>> of
>> Positive.
>
> The issue of the bounds of an empty string is not related to subtypes. It
> has a long history. But in short, you should not break one thing in order
> to save another.

I totally agree. You should build a time-machine in order to go back and 
tell Jean Ichbiah and his team that. But until you do, it is very relevant 
for Ada - because that is the decision that they made and we're stuck with 
it forever (including all weird consequences).

                                            Randy.






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

* Re: Is this expected behavior or not
  2013-03-12 17:42         ` Dmitry A. Kazakov
  2013-03-12 18:04           ` Georg Bauhaus
@ 2013-03-12 23:21           ` Randy Brukardt
  1 sibling, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-03-12 23:21 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:8klywqh2pf$.1f949flc1xeia.dlg@40tude.net...
> On Tue, 12 Mar 2013 13:19:06 -0400, Robert A Duff wrote:
...
>>>    for I in Prime'Range loop -- What is this supposed to mean?
>>>       ...
>>
>> It doesn't mean anything -- it's illegal.
>
> Why Prime'Succ is legal then?

You could argue that it should have been. But as it is an operation on a 
type, not a subtype, constraints and predicates aren't involved, so it 
doesn't need to be illegal.

> And what about:
>
>   for I in Prime'First..Prime'Last loop

'First and 'Last are also illegal on subtypes that have predicates. (See 
3.2.4(26/3)). I argued that this is wrong, in that these are also operations 
returning values of the base type. The above means:

    for I in Prime'Base range Prime'First .. Prime'Last loop

and that is quite meaningful. But there was concern over confusing this with

    for I in Prime loop

which clearly involves the subtype.

Making 'First and 'Last illegal also ties in with the impossibility of 
having an array indexed by a subtype with a predicate (which is nearly 
impossible to implement, especially because of the possibility of slices). 
That had to be illegal and the related features were carried along.

                                           Randy.





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

* Re: Is this expected behavior or not
  2013-03-12  9:17   ` Dmitry A. Kazakov
@ 2013-03-13  0:10     ` Shark8
  0 siblings, 0 replies; 242+ messages in thread
From: Shark8 @ 2013-03-13  0:10 UTC (permalink / raw)
  Cc: mailbox

On Tuesday, March 12, 2013 3:17:37 AM UTC-6, Dmitry A. Kazakov wrote:
> 
> If 'Succ is convariant in the argument, this shall raise Constraint_Error
> because 2 is not Prime.

And here I thought it was prime, in fact I would have made the claim that it is the only element of the set of even prime numbers.



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

* Re: Is this expected behavior or not
  2013-03-12 22:23               ` Georg Bauhaus
@ 2013-03-13  8:49                 ` Dmitry A. Kazakov
  2013-03-13  9:45                   ` J-P. Rosen
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-13  8:49 UTC (permalink / raw)


On Tue, 12 Mar 2013 23:23:52 +0100, Georg Bauhaus wrote:

> On 12.03.13 19:21, Dmitry A. Kazakov wrote:
>> On Tue, 12 Mar 2013 19:04:31 +0100, Georg Bauhaus wrote:
>>
>>> On 12.03.13 18:42, Dmitry A. Kazakov wrote:
>>>> On Tue, 12 Mar 2013 13:19:06 -0400, Robert A Duff wrote:
> 
>>>>>> The profile of 'Succ is given in RM-3.5(23):
>>>>>>
>>>>>>      function S'Succ (Arg: S'Base) return S'Base;
>>>>>>
>>>>>> It's neither contravariant nor covariant -- it's invariant.
>>>> Invariant = contravariant.
>>>
>>> In Ada? For non-tagged types?
>>
>> Tagged is a special case, nothing more.
>>
>> When the compiler allows instances of Prime in an operation of Prime'Base
>> that means that Prime inherits the operation
> 
> No inheritance involved here, in Ada, where the object involved simply is of
> an unconstrained subtype of the given type of Prime, which is not Prime.

You have two types T and S and one operation F. Provided Ada is a typed
language. F (X : T) shall not accept S, unless inherited. In Ada subtype
(here subtype is Ada-subtype) operations are inherited per composition with
conversion to the base type which is null for in-arguments and sometimes
range-check of outs (not always, though). E.g.

   F (X : S) = F (S'Base (X))

S is a subtype *because* it inherits F. All three statements are
equivalent:

1. S is a subtype of T
2. S inherits operations of T
3. S is substitutable in operations of T (syntactically, not LSP)

When you inherit with null-conversion, as it is the case with 'Succ you
break the semantics of the result, which is not new. It is well-known LSP
issue that contravariance of out-arguments/results is broken upon
specialization. Which is trivial to see.

Prime is not a subtype which can preserve Integer's 'Succ. Nothing can be
done about it. Neither can Prime preserve +,-,*,/. Prime is basically not
Integer. Not every set of integers is Integer, and subsetting /= subtyping.

> This type, not Prime (which isn't a type),

How so? Subtype certainly is a type.

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



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

* Re: Is this expected behavior or not
  2013-03-13  8:49                 ` Dmitry A. Kazakov
@ 2013-03-13  9:45                   ` J-P. Rosen
  2013-03-13 13:31                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-03-13  9:45 UTC (permalink / raw)


Le 13/03/2013 09:49, Dmitry A. Kazakov a �crit :
>  In Ada subtype
> (here subtype is Ada-subtype) operations are inherited per composition with
> conversion to the base type which is null for in-arguments and sometimes
> range-check of outs (not always, though). E.g.
> 
>    F (X : S) = F (S'Base (X))
> 
> S is a subtype *because* it inherits F.

Not at all. In Ada, a type is a set of values. A subtype is the SAME
TYPE, restricted to a subset of the values (the "constraint").

This feature does not exist in other OO languages, however it is not a
reason to try to force this notion on how a more or less similar effect
could be achieved in other languages. A subtype has the same operation
as its base type, not copies of the operations as with inheritance.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-13  9:45                   ` J-P. Rosen
@ 2013-03-13 13:31                     ` Dmitry A. Kazakov
  2013-03-13 14:34                       ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-13 13:31 UTC (permalink / raw)


On Wed, 13 Mar 2013 10:45:54 +0100, J-P. Rosen wrote:

> Le 13/03/2013 09:49, Dmitry A. Kazakov a �crit :
>>  In Ada subtype
>> (here subtype is Ada-subtype) operations are inherited per composition with
>> conversion to the base type which is null for in-arguments and sometimes
>> range-check of outs (not always, though). E.g.
>> 
>>    F (X : S) = F (S'Base (X))
>> 
>> S is a subtype *because* it inherits F.
> 
> Not at all. In Ada, a type is a set of values.

A type is a set of values bound by operations defined on them. It is
values+operations.

Even under your (wrong) definition Positive is still different from Integer
because Positive does not have values like -1.

> A subtype is the SAME
> TYPE, restricted to a subset of the values (the "constraint").

There is a simple empiric test to determine if two types are same. They are
if there is no language means to distinguish them either at compile or at
run-time.

Ada subtypes are proper types and they are distinguishable from each other
and their bases. E.g. these two programs are not equivalent:

   X : Integer := -1;

and

   X : Positive := -1;

You cannot replace Integer with Positive without changing the semantics of
any possible program, hence they are different.

Note that since the above is the weakest possible definition of
dissimilarity. Any other would be only stronger. Therefore, there is no way
to have Ada's Positive and Integer "same."
 
> A subtype has the same operation
> as its base type, not copies of the operations as with inheritance.

In a typed language any type has only operations of its own. All other
operations give type error.

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



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

* Re: Is this expected behavior or not
  2013-03-13 13:31                     ` Dmitry A. Kazakov
@ 2013-03-13 14:34                       ` Georg Bauhaus
  2013-03-13 15:51                         ` Dmitry A. Kazakov
  2013-03-13 17:05                         ` Shark8
  0 siblings, 2 replies; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-13 14:34 UTC (permalink / raw)


On 13.03.13 14:31, Dmitry A. Kazakov wrote:
> On Wed, 13 Mar 2013 10:45:54 +0100, J-P. Rosen wrote:
> 
>> Le 13/03/2013 09:49, Dmitry A. Kazakov a �crit :
>>>  In Ada subtype
>>> (here subtype is Ada-subtype) operations are inherited per composition with
>>> conversion to the base type which is null for in-arguments and sometimes
>>> range-check of outs (not always, though). E.g.
>>>
>>>    F (X : S) = F (S'Base (X))
>>>
>>> S is a subtype *because* it inherits F.
>>
>> Not at all. In Ada, a type is a set of values.
> 
> A type is a set of values bound by operations defined on them. It is
> values+operations.

The LRM does not define what it means for sets of values being
"bound by operations". It does define subtypes and types.

> Even under your (wrong) definition Positive is still different from Integer
> because Positive does not have values like -1.

I don't think this is true. In Ada, Positive and Integer are
not different types.
The names Positive and Integer refer to the same type; objects
happen to be associated with different range constraints.

See Ivan Godard's comment on his invention, the subtype in Ada:
http://newsgroups.derkeiler.com/Archive/Comp/comp.arch/2012-08/msg00360.html

> Ada subtypes are proper types

External observations inspired by whichever type theory do
not apply when judging things from the Ada perspective.
I'd find observations interesting only when someone is pondering
language design, not when explaining properties of an existing
language. Randy mentioned a time machine...

> E.g. these two programs are not equivalent:
> 
>    X : Integer := -1;
...
> You cannot replace Integer with Positive without changing the semantics of
> any possible program, hence they are different.

The difference only means that different range constraints yield
different programs. Nothing about different Ada types here.

  X : Integer := -2;

yields another semantically different program. Does the difference
(assigning -2, not -1) tell anything about the Ada type of X?
Constraint_Error on assigning a negative value to a variable
whose range constraint requires positive values is a consequence
of range checking *in* the same type's set.




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

* Re: Is this expected behavior or not
  2013-03-13 14:34                       ` Georg Bauhaus
@ 2013-03-13 15:51                         ` Dmitry A. Kazakov
  2013-03-13 16:56                           ` Jeffrey Carter
  2013-03-13 17:32                           ` Georg Bauhaus
  2013-03-13 17:05                         ` Shark8
  1 sibling, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-13 15:51 UTC (permalink / raw)


On Wed, 13 Mar 2013 15:34:41 +0100, Georg Bauhaus wrote:

> On 13.03.13 14:31, Dmitry A. Kazakov wrote:
>> On Wed, 13 Mar 2013 10:45:54 +0100, J-P. Rosen wrote:
>> 
>>> Le 13/03/2013 09:49, Dmitry A. Kazakov a �crit :
>>>>  In Ada subtype
>>>> (here subtype is Ada-subtype) operations are inherited per composition with
>>>> conversion to the base type which is null for in-arguments and sometimes
>>>> range-check of outs (not always, though). E.g.
>>>>
>>>>    F (X : S) = F (S'Base (X))
>>>>
>>>> S is a subtype *because* it inherits F.
>>>
>>> Not at all. In Ada, a type is a set of values.
>> 
>> A type is a set of values bound by operations defined on them. It is
>> values+operations.
> 
> The LRM does not define what it means for sets of values being
> "bound by operations". It does define subtypes and types.

LRM is irrelevant here. See

http://en.wikipedia.org/wiki/Abstract_data_type

>> Even under your (wrong) definition Positive is still different from Integer
>> because Positive does not have values like -1.
> 
> I don't think this is true.

Well, well, according to you Ada's Positive has -1 as a value?

>> Ada subtypes are proper types
> 
> External observations inspired by whichever type theory do
> not apply when judging things from the Ada perspective.

How a type theory may not apply to a programming language? Anyway if you
don't like the theory X, you should propose another theory.

But whichever theory you take, it cannot be consistent with Integer and
Positive being same type, while considering Ada typed.

Ada is typed. Integer and Positive are not same.

>> E.g. these two programs are not equivalent:
>> 
>>    X : Integer := -1;
> ...
>> You cannot replace Integer with Positive without changing the semantics of
>> any possible program, hence they are different.
> 
> The difference only means that different range constraints yield
> different programs.

The difference exists. q.e.d.

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



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

* Re: Is this expected behavior or not
  2013-03-13 15:51                         ` Dmitry A. Kazakov
@ 2013-03-13 16:56                           ` Jeffrey Carter
  2013-03-13 17:09                             ` Shark8
  2013-03-13 17:32                           ` Georg Bauhaus
  1 sibling, 1 reply; 242+ messages in thread
From: Jeffrey Carter @ 2013-03-13 16:56 UTC (permalink / raw)


On 03/13/2013 08:51 AM, Dmitry A. Kazakov wrote:
>
> LRM is irrelevant here.

The ARM is never irrelevant when discussing Ada.

-- 
Jeff Carter
"Ah, go away or I'll kill ya."
Never Give a Sucker an Even Break
100



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

* Re: Is this expected behavior or not
  2013-03-13 14:34                       ` Georg Bauhaus
  2013-03-13 15:51                         ` Dmitry A. Kazakov
@ 2013-03-13 17:05                         ` Shark8
  2013-03-13 17:45                           ` Simon Wright
  1 sibling, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-13 17:05 UTC (permalink / raw)


On Wednesday, March 13, 2013 8:34:41 AM UTC-6, Georg Bauhaus wrote:
> 
> External observations inspired by whichever type theory do
> not apply when judging things from the Ada perspective.
> I'd find observations interesting only when someone is pondering
> language design, not when explaining properties of an existing
> language. Randy mentioned a time machine...

I don't know, I think that if I could alter the the past (Ada 83) for some minor alterations it would be to include null-exclusion on access types... seems like that would have been far more useful in-practice than mucking about with 'Pred/'Succ or 'First/'Last. -- child packages would have been nice from the inception, but I don't think the compiler-writers would have tolerated the added complexity there given that as it was Ada 83 was pushing the bleeding-edge bounds of compiler technology.



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

* Re: Is this expected behavior or not
  2013-03-13 16:56                           ` Jeffrey Carter
@ 2013-03-13 17:09                             ` Shark8
  0 siblings, 0 replies; 242+ messages in thread
From: Shark8 @ 2013-03-13 17:09 UTC (permalink / raw)


On Wednesday, March 13, 2013 10:56:27 AM UTC-6, Jeffrey Carter wrote:
> On 03/13/2013 08:51 AM, Dmitry A. Kazakov wrote:
> 
> >
> > LRM is irrelevant here.
> 
> The ARM is never irrelevant when discussing Ada.

The only time the ARM could be irrelevant is when talking about "what ifs" like:
* What if Red had won?
* What if Ada 83 had child-packages?
* What if Ada 95 had "abstract types"/"type classes" so you could define a truly generic string? (One base-type that could handle Character, Wide_Character, or Wide_Wide_Character.)



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

* Re: Is this expected behavior or not
  2013-03-13 15:51                         ` Dmitry A. Kazakov
  2013-03-13 16:56                           ` Jeffrey Carter
@ 2013-03-13 17:32                           ` Georg Bauhaus
  2013-03-13 19:28                             ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-13 17:32 UTC (permalink / raw)


On 13.03.13 16:51, Dmitry A. Kazakov wrote:

> LRM is irrelevant here. See

The Ada LRM seems somewhat relevant when discussing
the workings of Ada type attributes and predicates.

> http://en.wikipedia.org/wiki/Abstract_data_type

Ada subtypes are not ADTs. Which is the point.

> Well, well, according to you Ada's Positive has -1 as a value?

The Ada type of Positive includes -1 as a value.


> How a type theory may not apply to a programming language? Anyway if you
> don't like the theory X, you should propose another theory.

Type as defined by the LRM; when the discussion is about how
you dislike what subtypes are, fine. However, seeing how
constraints and predicates work in Ada is not easier if
by some twist of the discussion the explanation becomes one
of how LSP and proper subsets create a well known problem in
a hypothetical or otherwise non-Ada language that involves
two different types, not Ada subtypes.

Let "subtype" be an Ada subtype, nothing else, and everything
becomes consistent again. Not necessarily clear, but consistent.
Maybe confusing, but consistent. Maybe counterintuitive, but
consistent.

> But whichever theory you take, it cannot be consistent with Integer and
> Positive being same type, while considering Ada typed.
> 
> Ada is typed. Integer and Positive are not same.

Not same what? Need a reference here. (There is an X such that
grapefruits and oranges are not same X. There is an X such that
Positive and Integer are not same X.)

>> The difference only means that different range constraints yield
>> different programs.
> 
> The difference exists. q.e.d.

You have shown that different constraints on objects of the
same type yield different programs. But this is not q.e.d.




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

* Re: Is this expected behavior or not
  2013-03-13 17:05                         ` Shark8
@ 2013-03-13 17:45                           ` Simon Wright
  2013-03-13 19:37                             ` Dmitry A. Kazakov
  2013-03-14 22:41                             ` Florian Weimer
  0 siblings, 2 replies; 242+ messages in thread
From: Simon Wright @ 2013-03-13 17:45 UTC (permalink / raw)


Shark8 <onewingedshark@gmail.com> writes:

> On Wednesday, March 13, 2013 8:34:41 AM UTC-6, Georg Bauhaus wrote:
>> 
>> External observations inspired by whichever type theory do
>> not apply when judging things from the Ada perspective.
>> I'd find observations interesting only when someone is pondering
>> language design, not when explaining properties of an existing
>> language. Randy mentioned a time machine...
>
> I don't know, I think that if I could alter the the past (Ada 83) for
> some minor alterations it would be to include null-exclusion on access
> types... seems like that would have been far more useful in-practice
> than mucking about with 'Pred/'Succ or 'First/'Last. -- child packages
> would have been nice from the inception, but I don't think the
> compiler-writers would have tolerated the added complexity there given
> that as it was Ada 83 was pushing the bleeding-edge bounds of compiler
> technology.

I don't remember ever using 'Pred/'Succ, but I'd sorely miss
'First/'Last.



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

* Re: Is this expected behavior or not
  2013-03-13 17:32                           ` Georg Bauhaus
@ 2013-03-13 19:28                             ` Dmitry A. Kazakov
  2013-03-13 21:01                               ` Randy Brukardt
                                                 ` (2 more replies)
  0 siblings, 3 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-13 19:28 UTC (permalink / raw)


On Wed, 13 Mar 2013 18:32:01 +0100, Georg Bauhaus wrote:

> On 13.03.13 16:51, Dmitry A. Kazakov wrote:
> 
>> http://en.wikipedia.org/wiki/Abstract_data_type
> 
> Ada subtypes are not ADTs. Which is the point.

And the difference is?

>> Well, well, according to you Ada's Positive has -1 as a value?
> 
> The Ada type of Positive includes -1 as a value.

This is where ARM becomes relevant again:

ARM 3-2(8/2):

"A subtype of a given type is a combination of the type, a constraint on
values of the type, and certain attributes specific to the subtype. The
given type is called the type of the subtype. Similarly, the associated
constraint is called the constraint of the subtype."

and the final blow:

"The set of values of a subtype consists of the values of its type that
satisfy its constraint and any exclusion of the null value. Such values
belong to the subtype."
 
>> How a type theory may not apply to a programming language? Anyway if you
>> don't like the theory X, you should propose another theory.
> 
> Type as defined by the LRM; when the discussion is about how
> you dislike what subtypes are, fine.

Where I said I dislike them?

What I said is that Ada subtype is a type-algebraic operation that produces
a new type which properties are described in ARM. There are other type
algebraic operations which produce array, record types, tagged extension,
class-wide types, generic expansions/instantiations etc. They all are used
to construct new *types* from existing ones.

> However, seeing how
> constraints and predicates work in Ada is not easier if
> by some twist of the discussion the explanation becomes one
> of how LSP and proper subsets create a well known problem in
> a hypothetical or otherwise non-Ada language that involves
> two different types, not Ada subtypes.

> Let "subtype" be an Ada subtype, nothing else, and everything
> becomes consistent again. Not necessarily clear, but consistent.
> Maybe confusing, but consistent. Maybe counterintuitive, but
> consistent.

You are welcome to show how problems of substitutability get solved without
these explanations.

'Succ has the problem of substitutability because of these problems. It is
due to multiple inheritance. Pred'Succ inherits some ordered interface from
Integer and from its own problem space. 'Succ is an operation of the
interfaces. These interfaces collide in Prime.

Ada's design choice was in favor of Integer's order: 'Succ (3)=4. But
user's expectation was the order from the problem space 'Succ(3)=5.

Now whatever definitions you take the problem is there. It is not a problem
of definitions.

>> But whichever theory you take, it cannot be consistent with Integer and
>> Positive being same type, while considering Ada typed.
>> 
>> Ada is typed. Integer and Positive are not same.
> 
> Not same what? Need a reference here.

Use any name you want for the corresponding entities. Whatever name you
choose, I am still able to construct a program which semantics would change
when Integer is substituted by Positive.

Positive is not always substitutable for Integer. However you re-write ARM,
that fact is to stay.

>>> The difference only means that different range constraints yield
>>> different programs.
>> 
>> The difference exists. q.e.d.
> 
> You have shown that different constraints on objects of the
> same type yield different programs. But this is not q.e.d.

I shown that objects of Integer and Positive have different properties.

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



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

* Re: Is this expected behavior or not
  2013-03-13 17:45                           ` Simon Wright
@ 2013-03-13 19:37                             ` Dmitry A. Kazakov
  2013-03-13 19:54                               ` Simon Wright
  2013-03-13 21:09                               ` Randy Brukardt
  2013-03-14 22:41                             ` Florian Weimer
  1 sibling, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-13 19:37 UTC (permalink / raw)


On Wed, 13 Mar 2013 17:45:56 +0000, Simon Wright wrote:

> I don't remember ever using 'Pred/'Succ,

Even in:

generic
   type Discrete is (<>);
package Foo is

?

Well, you could use Discrete'Val (Discrete'Pos (Index) + 1) as a substitute
for Discrete'Succ (Index).

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



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

* Re: Is this expected behavior or not
  2013-03-13 19:37                             ` Dmitry A. Kazakov
@ 2013-03-13 19:54                               ` Simon Wright
  2013-03-13 20:54                                 ` Dmitry A. Kazakov
  2013-03-13 21:47                                 ` Jeffrey Carter
  2013-03-13 21:09                               ` Randy Brukardt
  1 sibling, 2 replies; 242+ messages in thread
From: Simon Wright @ 2013-03-13 19:54 UTC (permalink / raw)


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

> On Wed, 13 Mar 2013 17:45:56 +0000, Simon Wright wrote:
>
>> I don't remember ever using 'Pred/'Succ,
>
> Even in:
>
> generic
>    type Discrete is (<>);
> package Foo is

Nope.

Out of over 200 packages I have only one with this construct: it is a
signature package, no need for 'Pred or 'Succ (in other words, the
enumeration defines a set of distinct possibilities, ordering
irrelevant).

   generic

      --  This package specifies the properties required of a Time for it
      --  to be used with event management.

      type Time_Kind is (<>);

      --  One of the kinds of Time must be Real_Time, used for "delay for".
      Real_Time : Time_Kind;

      type Time (Kind : Time_Kind) is private;

      with function From_Now (Period : Duration) return Time;

      with function Image (Of_Time : Time) return String;
      --  Used in logging versions of Event Queues.

   package ColdFrame.Time_Signature is
   end ColdFrame.Time_Signature;





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

* Re: Is this expected behavior or not
  2013-03-13 19:54                               ` Simon Wright
@ 2013-03-13 20:54                                 ` Dmitry A. Kazakov
  2013-03-13 21:28                                   ` Simon Wright
  2013-03-13 22:12                                   ` Robert A Duff
  2013-03-13 21:47                                 ` Jeffrey Carter
  1 sibling, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-13 20:54 UTC (permalink / raw)


On Wed, 13 Mar 2013 19:54:22 +0000, Simon Wright wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On Wed, 13 Mar 2013 17:45:56 +0000, Simon Wright wrote:
>>
>>> I don't remember ever using 'Pred/'Succ,
>>
>> Even in:
>>
>> generic
>>    type Discrete is (<>);
>> package Foo is
> 
> Nope.
> 
> Out of over 200 packages I have only one with this construct: it is a
> signature package, no need for 'Pred or 'Succ (in other words, the
> enumeration defines a set of distinct possibilities, ordering
> irrelevant).

You need (<>) as an ancestor of both mod <> and range <> in packages that
should be instantiated with either integer or modular type.

Ada needs explicit interfaces, so that you could declare an unordered
enumeration if you don't need order. However, from the practical
perspective that would be public view, privately you still need it ordered
in some ad-hoc way to be able to implement stream attributes, hash tables
etc.

P.S. This is how Ada could finally get curly brackets  (:-)):

   type Color is {Red, Green, Blue}; -- No order in public views

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



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

* Re: Is this expected behavior or not
  2013-03-13 19:28                             ` Dmitry A. Kazakov
@ 2013-03-13 21:01                               ` Randy Brukardt
  2013-03-13 21:18                                 ` Dmitry A. Kazakov
  2013-03-13 21:37                               ` Georg Bauhaus
  2013-03-13 22:34                               ` Robert A Duff
  2 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-13 21:01 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:vxjicagtvzjg.1bcu3fzy711ux$.dlg@40tude.net...
...
> What I said is that Ada subtype is a type-algebraic operation that 
> produces
> a new type which properties are described in ARM. There are other type
> algebraic operations which produce array, record types, tagged extension,
> class-wide types, generic expansions/instantiations etc. They all are used
> to construct new *types* from existing ones.

A subtype does not create a new type, the quote you made from the RM says as 
much. QED :-)

When talking about Ada, no one cares about abstract mis-definitions of the 
word "type" used by people who have no clue how to define a proper 
programming language. IMHO, Ada was the first language to get these things 
right (which I why I got professionally involved in Ada in the first 
place -- it was just a much better design than Pascal, C, or Modula, all of 
which I used before Ada). And ivory tower theories of programming language 
design are rarely worth the paper they're printed on -- it's not worth 
anyone's time to waste mental energy on that.

You have many interesting ideas that would be far better served if you 
described them in Ada-terms. You're consistent refusal to do so means that 
they mostly get ignored -- and Ada (and programming in general) is all the 
poorer for it.

                                           Randy.





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

* Re: Is this expected behavior or not
  2013-03-13 19:37                             ` Dmitry A. Kazakov
  2013-03-13 19:54                               ` Simon Wright
@ 2013-03-13 21:09                               ` Randy Brukardt
  2013-03-13 22:48                                 ` Shark8
  1 sibling, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-13 21:09 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:11rcs3gg4taww$.bylek8fsshyz$.dlg@40tude.net...
> On Wed, 13 Mar 2013 17:45:56 +0000, Simon Wright wrote:
>
>> I don't remember ever using 'Pred/'Succ,
>
> Even in:
>
> generic
>   type Discrete is (<>);
> package Foo is
>
> ?

I'm not Simon, but in generics I've only used loops on discrete types (the 
usual reason for such a type being to index an array). In almost all other 
cases, I've ended up taking 'Pos on them because real math was needed 
(masking, usually).

The not-defined procedure 'Succ would have been much more useful because it 
could replace expressions like:

    <Very_Long_Name> := <Very_Long_Name> + 1;

with

    <Very_Long_Name>'Succ;

which would eliminate the potential for errors, possibly generate better 
code (by not having to evaluate <Very_Long_Name> twice if it contains 
function calls), and eliminate the hair-brained calls for ":=+" operators 
(which don't even work for Ada).

                                       Randy.





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

* Re: Is this expected behavior or not
  2013-03-13 21:01                               ` Randy Brukardt
@ 2013-03-13 21:18                                 ` Dmitry A. Kazakov
  2013-03-14 21:51                                   ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-13 21:18 UTC (permalink / raw)


On Wed, 13 Mar 2013 16:01:27 -0500, Randy Brukardt wrote:

> You have many interesting ideas that would be far better served if you 
> described them in Ada-terms.

How do you describe tagged types in Ada 83 terms?

In order to move forward you need a consistent theory behind the language.
RM is not the place where you could do that work. RM is about engineering,
not science. You don't describe thermodynamic processes in terms of
Volkswagen Owner's Manual. Thermodynamics apply both to VW and GM,
regardless whatever manuals.

If the car does not work, but the manual says it should, trust the car.

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



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

* Re: Is this expected behavior or not
  2013-03-13 20:54                                 ` Dmitry A. Kazakov
@ 2013-03-13 21:28                                   ` Simon Wright
  2013-03-14  9:16                                     ` Dmitry A. Kazakov
  2013-03-13 22:12                                   ` Robert A Duff
  1 sibling, 1 reply; 242+ messages in thread
From: Simon Wright @ 2013-03-13 21:28 UTC (permalink / raw)


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

> On Wed, 13 Mar 2013 19:54:22 +0000, Simon Wright wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> 
>>> On Wed, 13 Mar 2013 17:45:56 +0000, Simon Wright wrote:
>>>
>>>> I don't remember ever using 'Pred/'Succ,
>>>
>>> Even in:
>>>
>>> generic
>>>    type Discrete is (<>);
>>> package Foo is
>> 
>> Nope.
>> 
>> Out of over 200 packages I have only one with this construct: it is a
>> signature package, no need for 'Pred or 'Succ (in other words, the
>> enumeration defines a set of distinct possibilities, ordering
>> irrelevant).
>
> You need (<>) as an ancestor of both mod <> and range <> in packages
> that should be instantiated with either integer or modular type.

I don't understand this.

Anyway, as I said, only 0.5% of the packages I have written (and that I
have on this machine) have a formal discrete type definition, and
'Pred/'Succ were irrelevant for that one.



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

* Re: Is this expected behavior or not
  2013-03-13 19:28                             ` Dmitry A. Kazakov
  2013-03-13 21:01                               ` Randy Brukardt
@ 2013-03-13 21:37                               ` Georg Bauhaus
  2013-03-14 11:18                                 ` Dmitry A. Kazakov
  2013-03-13 22:34                               ` Robert A Duff
  2 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-13 21:37 UTC (permalink / raw)


On 13.03.13 20:28, Dmitry A. Kazakov wrote:

>> Ada subtypes are not ADTs. Which is the point.
>
> And the difference is?

Several:
Incomparable.
In Ada, ADT is not defined.
An ADT is a model of thought that can be mapped to constructs.
I find it moderately useful to insist on problems with predicates
that only exist in the ADT/LSP model, but not in Ada (where there
simply is no variance in this case due to the definition of 'Succ).

>>> Well, well, according to you Ada's Positive has -1 as a value?
>>
>> The Ada type of Positive includes -1 as a value.
>
> This is where ARM becomes relevant again:
>
> ARM 3-2(8/2):

ARM 3.2(8/2) implies that "the type of Positive includes the value -1"
(the type of Positive is not the subtype Positive). For example, with
one compiler,

values_of(Positive) = { x : x ∈ values_of(type_of(Positive)) |
    x ≧ 1 & x ≦ 2³¹-1 }

The paragraph you have quoted from the LRM thus indicates that the value
-1 belongs to the type of Positive, but -1 does not belong to what Ada
calls a subtype. Hence, again, the type of Positive includes the value -1,
but the subtype Positive does not.

Let me see if I understand the claim that a subtype declarations is
a type-algebraic operation correctly, with Ada in mind:

One starts from types to produce new types.

   type V is array (S) of T;

declares a new type (and its ...). But

   subtype V is Integer range -2 .. +34;

does not declare a new type (LRM 3.2.2(1)). Only some re-interpretation of
Ada terms creates a notion of subtype that Ada does not seem to support,
really. One can do this, but when solving a problem with (a misreading of)
'Succ, doing so only emphasizes the cause of the problem, which is assuming
that a subtype can be treated the same way as a type or ADT.


> You are welcome to show how problems of substitutability get solved without
> these explanations.

There is no substitutability issue whatsoever for parameters of 'Succ
because 'Succ is not defined in terms of types that could introduce the
problem. This definition may not be as desired, but the problem is extraneous
from an Ada perspective. Instead, I could define (like you have done many
times before):

    type T is private ...;

    function Succ (X : T) return T
      with ...;

when I need to map T to an algebraic data type.


>  It is not a problem of definitions.

Is it *solely* a problem of definitions from the non-Ada world.


> I shown that objects of Integer and Positive have different properties.

The difference is entirely a consequence of different constraints on the
same type that Integer and Positive share.
I wondered why you have avoided the word "type" here and use "properties"
instead?




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

* Re: Is this expected behavior or not
  2013-03-13 19:54                               ` Simon Wright
  2013-03-13 20:54                                 ` Dmitry A. Kazakov
@ 2013-03-13 21:47                                 ` Jeffrey Carter
  1 sibling, 0 replies; 242+ messages in thread
From: Jeffrey Carter @ 2013-03-13 21:47 UTC (permalink / raw)


On 03/13/2013 12:54 PM, Simon Wright wrote:
>
> Out of over 200 packages I have only one with this construct: it is a
> signature package, no need for 'Pred or 'Succ (in other words, the
> enumeration defines a set of distinct possibilities, ordering
> irrelevant).

The sorting algorithms in the PragmAda Reusable Components have a generic formal 
part like

generic -- PragmARC.Sort_Heap
    type Element  is private;
    type Index    is (<>);
    type Sort_Set is array (Index range <>) of Element;

    with function "<" (Left : Element; Right : Element) return Boolean is <>;
procedure PragmARC.Sort_Heap (Set : in out Sort_Set);

and use Index'Pred and Index'Succ.

-- 
Jeff Carter
"Ah, go away or I'll kill ya."
Never Give a Sucker an Even Break
100



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

* Re: Is this expected behavior or not
  2013-03-13 20:54                                 ` Dmitry A. Kazakov
  2013-03-13 21:28                                   ` Simon Wright
@ 2013-03-13 22:12                                   ` Robert A Duff
  1 sibling, 0 replies; 242+ messages in thread
From: Robert A Duff @ 2013-03-13 22:12 UTC (permalink / raw)


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

> P.S. This is how Ada could finally get curly brackets  (:-)):
>
>    type Color is {Red, Green, Blue}; -- No order in public views

An early version of Ada (Green?) had unordered enumeration types.
I don't remember the syntax, but it didn't involve curly braces.  ;-)

GNAT has a pragma Ordered to mark an enumeration type as ordered,
and a switch -gnatw.u that tells the compiler to complain if
you use certain operations on unordered enums (unordered being
the default).

- Bob



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

* Re: Is this expected behavior or not
  2013-03-13 19:28                             ` Dmitry A. Kazakov
  2013-03-13 21:01                               ` Randy Brukardt
  2013-03-13 21:37                               ` Georg Bauhaus
@ 2013-03-13 22:34                               ` Robert A Duff
  2013-03-14  9:09                                 ` Dmitry A. Kazakov
  2 siblings, 1 reply; 242+ messages in thread
From: Robert A Duff @ 2013-03-13 22:34 UTC (permalink / raw)


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

> Ada's design choice was in favor of Integer's order: 'Succ (3)=4. But
> user's expectation was the order from the problem space 'Succ(3)=5.

As a user, what is your expectation for the following?

    X : Prime := 3;

    A : Integer := Prime'Succ (X); -- A = 4
    B : Integer := Integer'Succ (X); -- B = 4
    C : Integer := X + 1; -- C = 4
    D : Prime := X + 1; -- Constraint_Error on the ":=", not on the "+"

    E : Integer := Positive'Pred(1); -- E = 0
    F : Integer := Positive'Pred(-100); -- F = -101

    type T is range 1..10;
    G : T := 10;
    H : T := 10;
    I : T := (G + H) / 2; -- I = 10

I've shown the actual Ada semantics in comments.
Does your expectation differ?

(Nitpick: The expression G+H could overflow, if the compiler
chose a base range for T of -10..10.  No compiler does that,
but if you're worried about it, you could declare
"type T is new Integer range 1..10" instead.)

- Bob



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

* Re: Is this expected behavior or not
  2013-03-13 21:09                               ` Randy Brukardt
@ 2013-03-13 22:48                                 ` Shark8
  2013-03-14 22:01                                   ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-13 22:48 UTC (permalink / raw)


On Wednesday, March 13, 2013 3:09:24 PM UTC-6, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> 
> news:11rcs3gg4taww$.bylek8fsshyz$.dlg@40tude.net...
> 
> > On Wed, 13 Mar 2013 17:45:56 +0000, Simon Wright wrote:
> >
> >> I don't remember ever using 'Pred/'Succ,
> >
> > Even in:
> > generic
> >   type Discrete is (<>);
> > package Foo is
> > ?
> 
> I'm not Simon, but in generics I've only used loops on discrete types (the 
> usual reason for such a type being to index an array). In almost all other 
> cases, I've ended up taking 'Pos on them because real math was needed 
> (masking, usually).
> 
> The not-defined procedure 'Succ would have been much more useful because it 
> could replace expressions like:
> 
>     <Very_Long_Name> := <Very_Long_Name> + 1;
> with
>     <Very_Long_Name>'Succ;
> 
> which would eliminate the potential for errors, possibly generate better 
> code (by not having to evaluate <Very_Long_Name> twice if it contains 
> function calls), and eliminate the hair-brained calls for ":=+" operators 
> (which don't even work for Ada).
> 

Would there be a problem using this?

    Generic
	Type T is (<>);
	with function Succ(Input : T) Return T is T'Succ;
    package Test is
	-- Body does whatever is needed requiring Very_Long_Name as T.
    end Test;



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

* Re: Is this expected behavior or not
  2013-03-13 22:34                               ` Robert A Duff
@ 2013-03-14  9:09                                 ` Dmitry A. Kazakov
  2013-03-14  9:27                                   ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-14  9:09 UTC (permalink / raw)


On Wed, 13 Mar 2013 18:34:35 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> Ada's design choice was in favor of Integer's order: 'Succ (3)=4. But
>> user's expectation was the order from the problem space 'Succ(3)=5.
> 
> As a user, what is your expectation for the following?

My expectation is that the language should not let me doing this without
requesting explicit specification of which interfaces and implementations
get inherited.

Prime is clearly not integer, so if I inherit from it publicly while
applying some constraint which is not a range, I must be required to
override all numeric operations, all relational operations, all operations
that depends on ordering IF I want them.

But the default if, there should be any, must be no such operations
inherited.

There is too much going under the carpet, which is wrong. Ada must have
explicit interfaces manifested. RM 3.5.5, 3.5.8, 3.5.10 etc are nothing but
descriptions of interfaces. They shall have names. And it must be said that
a declaration like

   type T is range A..B;

is a shortcut for a more explicit declaration of T inheriting interfaces of
a scalar object, a comparable object, a numeric object, an ordered object,
a copyiable object etc.

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



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

* Re: Is this expected behavior or not
  2013-03-13 21:28                                   ` Simon Wright
@ 2013-03-14  9:16                                     ` Dmitry A. Kazakov
  2013-03-14 16:42                                       ` Simon Wright
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-14  9:16 UTC (permalink / raw)


On Wed, 13 Mar 2013 21:28:03 +0000, Simon Wright wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On Wed, 13 Mar 2013 19:54:22 +0000, Simon Wright wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>> 
>>>> On Wed, 13 Mar 2013 17:45:56 +0000, Simon Wright wrote:
>>>>
>>>>> I don't remember ever using 'Pred/'Succ,
>>>>
>>>> Even in:
>>>>
>>>> generic
>>>>    type Discrete is (<>);
>>>> package Foo is
>>> 
>>> Nope.
>>> 
>>> Out of over 200 packages I have only one with this construct: it is a
>>> signature package, no need for 'Pred or 'Succ (in other words, the
>>> enumeration defines a set of distinct possibilities, ordering
>>> irrelevant).
>>
>> You need (<>) as an ancestor of both mod <> and range <> in packages
>> that should be instantiated with either integer or modular type.
> 
> I don't understand this.

Let you have a generic package you wanted to be able o instantiate with
either Unsigned_16 or Integer. The formal generic type for that is formal
discrete. E.g.

generic
   type Index_Type is (<>);
   type Element_Type is private;
package Generic_Array is ...

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



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

* Re: Is this expected behavior or not
  2013-03-14  9:09                                 ` Dmitry A. Kazakov
@ 2013-03-14  9:27                                   ` Georg Bauhaus
  0 siblings, 0 replies; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-14  9:27 UTC (permalink / raw)


On 14.03.13 10:09, Dmitry A. Kazakov wrote:
> And it must be said that
> a declaration like
>
>     type T is range A..B;
>
> is a shortcut for a more explicit declaration of T inheriting interfaces of
> a scalar object, a comparable object, a numeric object, an ordered object,
> a copyiable object etc.

+1

With the proviso that the compatibility obstacle requires restraint,
I'd suggest

    type R is abstract range 0 .. 1;

    type T is abstract new Float;

as a starting point. Is "abstract ..." compatible with previous versions
of the language?




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

* Re: Is this expected behavior or not
  2013-03-13 21:37                               ` Georg Bauhaus
@ 2013-03-14 11:18                                 ` Dmitry A. Kazakov
  2013-03-14 12:37                                   ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-14 11:18 UTC (permalink / raw)


On Wed, 13 Mar 2013 22:37:49 +0100, Georg Bauhaus wrote:

> On 13.03.13 20:28, Dmitry A. Kazakov wrote:
> 
>>> Ada subtypes are not ADTs. Which is the point.
>>
>> And the difference is?
> 
> Several:
> Incomparable.
> In Ada, ADT is not defined.

How exactly Ada's Positive is not an abstract data type?

>>>> Well, well, according to you Ada's Positive has -1 as a value?
>>>
>>> The Ada type of Positive includes -1 as a value.
>>
>> This is where ARM becomes relevant again:
>>
>> ARM 3-2(8/2):
> 
> ARM 3.2(8/2) implies that "the type of Positive includes the value -1"
> (the type of Positive is not the subtype Positive).

We don't talk about Positive'Base. We do about Positive.

> Let me see if I understand the claim that a subtype declarations is
> a type-algebraic operation correctly, with Ada in mind:
> 
> One starts from types to produce new types.
> 
>    type V is array (S) of T;
> 
> declares a new type (and its ...). But
> 
>    subtype V is Integer range -2 .. +34;
> 
> does not declare a new type (LRM 3.2.2(1)).

Nevertheless

   Positive'Base /= Positive

and both are types.

>> You are welcome to show how problems of substitutability get solved without
>> these explanations.
> 
> There is no substitutability issue whatsoever for parameters of 'Succ
> because 'Succ is not defined in terms of types that could introduce the
> problem.

I don't understand. What is defined, in which terms, what introduces or not
problems?

> This definition may not be as desired,

Definition of what?

>>  It is not a problem of definitions.
> 
> Is it *solely* a problem of definitions from the non-Ada world.

So, it is prime numbers which are broken. Good to know... 

>> I shown that objects of Integer and Positive have different properties.
> 
> The difference is entirely a consequence of different constraints on the
> same type that Integer and Positive share.

Irrelevant. The difference is here. Period.

> I wondered why you have avoided the word "type" here and use "properties"
> instead?

You objected the word type. Call it "task" if you want to. It is still not
Integer.

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



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

* Re: Is this expected behavior or not
  2013-03-14 11:18                                 ` Dmitry A. Kazakov
@ 2013-03-14 12:37                                   ` Georg Bauhaus
  2013-03-14 14:26                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-14 12:37 UTC (permalink / raw)


On 14.03.13 12:18, Dmitry A. Kazakov wrote:
> On Wed, 13 Mar 2013 22:37:49 +0100, Georg Bauhaus wrote:
> 
>> On 13.03.13 20:28, Dmitry A. Kazakov wrote:
>>
>>>> Ada subtypes are not ADTs. Which is the point.
>>>
>>> And the difference is?
>>
>> Several:
>> Incomparable.
>> In Ada, ADT is not defined.
> 
> How exactly Ada's Positive is not an abstract data type?

Because ADTs are constructs of human mapping from a model space to the
space of language constructs. In this case the latter is defined in Ada
terms. The human's mapping activity causes the---legitimate---
problem with subtype constraints.

> We don't talk about Positive'Base. We do about Positive.

Positive'Succ does *not* declare parameters whose subtype is Positive.
This fact answers most of the other comments, I should think.

For a start, LRM 3.5 again,

22    S'Succ  S'Succ denotes a function with the following specification:

            23    function S'Succ(Arg : S'Base)
                    return S'Base

We don't talk about Positive'Base, you say?

>>    subtype V is Integer range -2 .. +34;
>>
>> does not declare a new type (LRM 3.2.2(1)).
> 
> Nevertheless
> 
>    Positive'Base /= Positive
> 
> and both are types.

The second claim is not true in Ada as relevant to this discussion,
because Positive's subtype constraint does not introduce a type.

>>>  It is not a problem of definitions.
>>
>> Is it *solely* a problem of definitions from the non-Ada world.
> 
> So, it is prime numbers which are broken. Good to know... 

Prime numbers are not defined in Ada, so the definition of Ada cannot
break them. The subtype named Prime that was given was essentially a
constraining predicate. If anyone thinks that 'Succ can be
re-interpreted to refer to a non-interval subset of integral numbers
of an Ada type, and it can't, then that's the problem: A plausible
assumption about the definition vs the actual definition.

>>> I shown that objects of Integer and Positive have different properties.
>>
>> The difference is entirely a consequence of different constraints on the
>> same type that Integer and Positive share.
> 
> Irrelevant. The difference is here. Period.

It is proof that Ada subtypes (not Ada types) and LSP (plus, in this
case, a re-interpretation of 'Succ based on incorrect premises) causes
problems with constraints (not types). The compiler does not reject
  x : Positive := -1,
so there is no Ada typing problem.

There are two problems instead:

1) to think that a subtype creates a type

2) to assume that 'Succ is not what it is





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

* Re: Is this expected behavior or not
  2013-03-14 12:37                                   ` Georg Bauhaus
@ 2013-03-14 14:26                                     ` Dmitry A. Kazakov
  2013-03-14 14:57                                       ` Georg Bauhaus
                                                         ` (2 more replies)
  0 siblings, 3 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-14 14:26 UTC (permalink / raw)


On Thu, 14 Mar 2013 13:37:44 +0100, Georg Bauhaus wrote:

>> How exactly Ada's Positive is not an abstract data type?
> 
> Because ADTs are constructs of human mapping from a model space to the
> space of language constructs. In this case the latter is defined in Ada
> terms.

That does not answer the question. ADT is a set of values and operations.
Please, show how Positive is different from that.

>> We don't talk about Positive'Base. We do about Positive.
> 
> Positive'Succ does *not* declare parameters whose subtype is Positive.

Surely it does. Proof:

   X : Positive := 1;
   Y : Positive := Positive'Succ (X);

Either Ada is untyped or else Positive'Succ is effectively defined on
Positive and returns Positive.

> 22    S'Succ  S'Succ denotes a function with the following specification:
> 
>             23    function S'Succ(Arg : S'Base)
>                     return S'Base
> 
> We don't talk about Positive'Base, you say?

Yes, since the language allows usage Positive with Positive'Succ that
automatically means that Positive has this operation.

>>>    subtype V is Integer range -2 .. +34;
>>>
>>> does not declare a new type (LRM 3.2.2(1)).
>> 
>> Nevertheless
>> 
>>    Positive'Base /= Positive
>> 
>> and both are types.
> 
> The second claim is not true in Ada as relevant to this discussion,
> because Positive's subtype constraint does not introduce a type.

Any set of values and operations introduces an abstract data type per
definition of.

Compare: C++ reference manual uses the term "class" for what is ADT. That
does not make C++ classes non-types. They still are.

>>>>  It is not a problem of definitions.
>>>
>>> Is it *solely* a problem of definitions from the non-Ada world.
>> 
>> So, it is prime numbers which are broken. Good to know... 
> 
> Prime numbers are not defined in Ada, so the definition of Ada cannot
> break them. The subtype named Prime that was given was essentially a
> constraining predicate. If anyone thinks that 'Succ can be
> re-interpreted to refer to a non-interval subset of integral numbers
> of an Ada type, and it can't, then that's the problem: A plausible
> assumption about the definition vs the actual definition.

That is a language problem. Dynamic predicates will be seen, felt and used
as abstract data types. This is why they should not be there. They
effectively make the language typing weaker.

And they are against the core Ada design idea that any implicit choice must
be safe and any unsafe choice explicit.

Inheritance of 'Succ is unsafe for certain types of constraints.

> There are two problems instead:
> 
> 1) to think that a subtype creates a type

It certainly does. Positive /= Integer and the inequality here is in Ada
terms.

> 2) to assume that 'Succ is not what it is

Exactly, ARM assumed something about programmer's intentions regarding the
subtype Prime and failed miserably. So did PL/1 with its ad-hoc type
conversions.

Ada designers knew all that in 80's.

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



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

* Re: Is this expected behavior or not
  2013-03-14 14:26                                     ` Dmitry A. Kazakov
@ 2013-03-14 14:57                                       ` Georg Bauhaus
  2013-03-14 15:51                                         ` Anh Vo
  2013-03-14 16:21                                       ` J-P. Rosen
  2013-03-14 16:22                                       ` Shark8
  2 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-14 14:57 UTC (permalink / raw)


On 14.03.13 15:26, Dmitry A. Kazakov wrote:
> Dynamic predicates will be seen, felt and used
> as abstract data types

Well put, and this can put an end to a discussion
based on nothing but a lexical ambiguity of "type".



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

* Re: Is this expected behavior or not
  2013-03-14 14:57                                       ` Georg Bauhaus
@ 2013-03-14 15:51                                         ` Anh Vo
  0 siblings, 0 replies; 242+ messages in thread
From: Anh Vo @ 2013-03-14 15:51 UTC (permalink / raw)


On Thursday, March 14, 2013 7:57:18 AM UTC-7, Georg Bauhaus wrote:
> On 14.03.13 15:26, Dmitry A. Kazakov wrote: 
> Dynamic predicates will be seen, felt and used 
> as abstract data types Well put, and this can put an end to a discussion based on nothing but a lexical ambiguity of "type".

I am hesitate to chime in since the discussion was way over my head. Back to my original question, I have found another way to accomplish my task. Thank you all for your input.



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

* Re: Is this expected behavior or not
  2013-03-14 14:26                                     ` Dmitry A. Kazakov
  2013-03-14 14:57                                       ` Georg Bauhaus
@ 2013-03-14 16:21                                       ` J-P. Rosen
  2013-03-14 17:29                                         ` Dmitry A. Kazakov
  2013-03-14 16:22                                       ` Shark8
  2 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-03-14 16:21 UTC (permalink / raw)


Le 14/03/2013 15:26, Dmitry A. Kazakov a �crit :
>> Because ADTs are constructs of human mapping from a model space to the
>> > space of language constructs. In this case the latter is defined in Ada
>> > terms.
> That does not answer the question. ADT is a set of values and operations.
> Please, show how Positive is different from that.
> 
The set of values is not defined by Positive, it is defined by Integer.
Positive is a name to designate a subset of these values.

>> There are two problems instead:
>>
>> 1) to think that a subtype creates a type
> 
> It certainly does. Positive /= Integer and the inequality here is in Ada
> terms.
> 
Ada allows assignment only if both sides are of the same type. You can
assign Integer to Positive, and conversely. Therefore, Positive and
Integer are the same type. qed.

And please, we are talking about Ada here, not KOVOA (Kasakov's Own View
of Ada).
-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-14 14:26                                     ` Dmitry A. Kazakov
  2013-03-14 14:57                                       ` Georg Bauhaus
  2013-03-14 16:21                                       ` J-P. Rosen
@ 2013-03-14 16:22                                       ` Shark8
  2013-03-14 17:08                                         ` Dmitry A. Kazakov
  2 siblings, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-14 16:22 UTC (permalink / raw)
  Cc: mailbox

On Thursday, March 14, 2013 8:26:56 AM UTC-6, Dmitry A. Kazakov wrote:
> On Thu, 14 Mar 2013 13:37:44 +0100, Georg Bauhaus wrote:
> 
> >> We don't talk about Positive'Base. We do about Positive.
> > 
> > Positive'Succ does *not* declare parameters whose subtype is Positive.
> 
> Surely it does. Proof:
> 
>    X : Positive := 1;
>    Y : Positive := Positive'Succ (X);
> 
> Either Ada is untyped or else Positive'Succ is effectively defined on
> Positive and returns Positive.

Objection!
The LRM says this about Types and Subtypes in 3.2 (8/2): 

A subtype of a given type is a combination of the type, a constraint on values of the type, and certain attributes specific to the subtype. The given type is called the type of the subtype. Similarly, the associated constraint is called the constraint of the subtype. The set of values of a subtype consists of the values of its type that satisfy its constraint and any exclusion of the null value. Such values belong to the subtype.

So then the TYPE of Positive is it's base, Integer (even if declared as a subtype of Natural, precisely because the TYPE of natural would also be Integer). If the parameters and results of 'Succ & 'Pred are of 'Base then they must obviously be able to take parameters of the given [SUB]TYPE because it's TYPE *is* 'Base.



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

* Re: Is this expected behavior or not
  2013-03-14  9:16                                     ` Dmitry A. Kazakov
@ 2013-03-14 16:42                                       ` Simon Wright
  2013-03-14 17:05                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Simon Wright @ 2013-03-14 16:42 UTC (permalink / raw)


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

> On Wed, 13 Mar 2013 21:28:03 +0000, Simon Wright wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> 
>>> You need (<>) as an ancestor of both mod <> and range <> in packages
>>> that should be instantiated with either integer or modular type.
>> 
>> I don't understand this.
>
> Let you have a generic package you wanted to be able o instantiate with
> either Unsigned_16 or Integer. The formal generic type for that is formal
> discrete. E.g.
>
> generic
>    type Index_Type is (<>);
>    type Element_Type is private;
> package Generic_Array is ...

Oh. When you used the word 'ancestor' I thought you were talking about
inheritance or type derivation.



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

* Re: Is this expected behavior or not
  2013-03-14 16:42                                       ` Simon Wright
@ 2013-03-14 17:05                                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-14 17:05 UTC (permalink / raw)


On Thu, 14 Mar 2013 16:42:24 +0000, Simon Wright wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On Wed, 13 Mar 2013 21:28:03 +0000, Simon Wright wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>> 
>>>> You need (<>) as an ancestor of both mod <> and range <> in packages
>>>> that should be instantiated with either integer or modular type.
>>> 
>>> I don't understand this.
>>
>> Let you have a generic package you wanted to be able o instantiate with
>> either Unsigned_16 or Integer. The formal generic type for that is formal
>> discrete. E.g.
>>
>> generic
>>    type Index_Type is (<>);
>>    type Element_Type is private;
>> package Generic_Array is ...
> 
> Oh. When you used the word 'ancestor' I thought you were talking about
> inheritance or type derivation.

That is same. Generic formal types form a class. The class (<>) includes
both the class range <> and the class mod <>. In this sense is it an
ancestor similarly how a tagged parent type or a base type is for a derived
type.

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



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

* Re: Is this expected behavior or not
  2013-03-14 16:22                                       ` Shark8
@ 2013-03-14 17:08                                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-14 17:08 UTC (permalink / raw)


On Thu, 14 Mar 2013 09:22:40 -0700 (PDT), Shark8 wrote:

> On Thursday, March 14, 2013 8:26:56 AM UTC-6, Dmitry A. Kazakov wrote:
>> On Thu, 14 Mar 2013 13:37:44 +0100, Georg Bauhaus wrote:
>> 
>>>> We don't talk about Positive'Base. We do about Positive.
>>> 
>>> Positive'Succ does *not* declare parameters whose subtype is Positive.
>> 
>> Surely it does. Proof:
>> 
>>    X : Positive := 1;
>>    Y : Positive := Positive'Succ (X);
>> 
>> Either Ada is untyped or else Positive'Succ is effectively defined on
>> Positive and returns Positive.
> 
> Objection!
[...]

The code is before your eyes. Operation is called on a Positive => Positive
has this operation.

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



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

* Re: Is this expected behavior or not
  2013-03-14 16:21                                       ` J-P. Rosen
@ 2013-03-14 17:29                                         ` Dmitry A. Kazakov
  2013-03-14 18:16                                           ` Georg Bauhaus
  2013-03-14 22:12                                           ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-14 17:29 UTC (permalink / raw)


On Thu, 14 Mar 2013 17:21:23 +0100, J-P. Rosen wrote:

> Le 14/03/2013 15:26, Dmitry A. Kazakov a �crit :
>>> Because ADTs are constructs of human mapping from a model space to the
>>> > space of language constructs. In this case the latter is defined in Ada
>>> > terms.
>> That does not answer the question. ADT is a set of values and operations.
>> Please, show how Positive is different from that.
>> 
> The set of values is not defined by Positive, it is defined by Integer.

Still, Positive has values, and operations.

> Positive is a name to designate a subset of these values.

And Integer is a name to designate a subset of Z. And Z is a subset of R or
Q. And R is a subset of C. Why does it matter?

>>> There are two problems instead:
>>>
>>> 1) to think that a subtype creates a type
>> 
>> It certainly does. Positive /= Integer and the inequality here is in Ada
>> terms.
>> 
> Ada allows assignment only if both sides are of the same type. You can
> assign Integer to Positive, and conversely. Therefore, Positive and
> Integer are the same type.

You forgot other possibilities:

1. The premise is wrong. It is, Ada indeed allows assignment of different
types. Example:

   type T is tagged null record;
   X : T'Class := T'(null record);

I hope you will not claim that T'Class and T are the same type.

2. Assignment is a primitive operation of the corresponding class of
related types which effectively permits profiles like:

   procedure ":=" (Left : in out Integer; Right : Integer);
   procedure ":=" (Left : in out Positive; Right : Integer);
   procedure ":=" (Left : in out Integer; Right : Positive);
   procedure ":=" (Left : in out Positive; Right : Positive);

Observe that in Ada these bodies are different. E.g. the second may raise
Constraint_Error.

I didn't say that Positive is unrelated to Integer type. It is a subtype
of. Yet it is a distinct type with a set of values and a set of operations. 

In order to be "sub-something" you must be "something" first.

> And please, we are talking about Ada here, not KOVOA (Kasakov's Own View
> of Ada).

Yes, it is my view of Ada. You have yours. What is wrong with that?

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



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

* Re: Is this expected behavior or not
  2013-03-14 17:29                                         ` Dmitry A. Kazakov
@ 2013-03-14 18:16                                           ` Georg Bauhaus
  2013-03-15  9:33                                             ` Dmitry A. Kazakov
  2013-03-14 22:12                                           ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-14 18:16 UTC (permalink / raw)


On 14.03.13 18:29, Dmitry A. Kazakov wrote:
>> > And please, we are talking about Ada here, not KOVOA (Kasakov's Own View
>> > of Ada).
> Yes, it is my view of Ada. You have yours. What is wrong with that?

An analogy:

The language C is an O-O language because the following is
both standard conforming and consistent with ADT views of C:

  Convert a void* to a struct that has a vtbl-Pointer
  that points to another struct (equally convertible
  from void*) that has a function pointer. Everything
  is type checked. This construct allows everything
  one needs in O-O programming.

The programs following this view exhibit a view of C as a language
whose structs obviously create inheritable O-O types that have
operations, all in the sense of perfect ADTs.

C is clearly an O-O language, then, since you can observe the
behavior of such programs to be O-O.

This style of argument will challenge other views of C
in the style of a provocation that requires much work
to set straight.

Maybe the time is better spent on outlining the addition
of abstract scalar types to Ada?




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

* Re: Is this expected behavior or not
  2013-03-13 21:18                                 ` Dmitry A. Kazakov
@ 2013-03-14 21:51                                   ` Randy Brukardt
  2013-03-15  1:10                                     ` Adam Beneschan
  2013-03-15  9:20                                     ` Dmitry A. Kazakov
  0 siblings, 2 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-03-14 21:51 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:13y3efy877tjl$.5yuu230sknnq$.dlg@40tude.net...
> On Wed, 13 Mar 2013 16:01:27 -0500, Randy Brukardt wrote:
>
>> You have many interesting ideas that would be far better served if you
>> described them in Ada-terms.
>
> How do you describe tagged types in Ada 83 terms?

Why would I want to? Tagged types aren't part of Ada 83. In any case, only 
Ada 2012 plus fixes is relevant; everything else is buggier or incomplete.

> In order to move forward you need a consistent theory behind the language.

Right, and Ada has one explained in the RM.

> RM is not the place where you could do that work. RM is about engineering,
> not science. You don't describe thermodynamic processes in terms of
> Volkswagen Owner's Manual. Thermodynamics apply both to VW and GM,
> regardless whatever manuals.

No one cares about that. You don't need to know about the laws of 
thermodynamics to operate a caase, and you don't need to know anything about 
type-algebras or other such baloney to program in a programming language. 
And it's the use of a programming language - not theories - that determines 
whether or not the language is truly usable.

Another way to put it is that raw science (as you called it) is essentially 
irrelevant unless it can be applied to engineering. After all, *ideas* are 
worthless; only execution has value in today's world. I care about the 
execution (that is the usability of the design) of Ada, not how it fits into 
someone's theory of how things should be.

                                       Randy.





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

* Re: Is this expected behavior or not
  2013-03-13 22:48                                 ` Shark8
@ 2013-03-14 22:01                                   ` Randy Brukardt
  2013-03-15  3:27                                     ` Shark8
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-14 22:01 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:99929f93-b80f-47c3-8a37-c81002733754@googlegroups.com...
> On Wednesday, March 13, 2013 3:09:24 PM UTC-6, Randy Brukardt wrote:
...
>> The not-defined procedure 'Succ would have been much more useful because 
>> it
>> could replace expressions like:
>>
>>     <Very_Long_Name> := <Very_Long_Name> + 1;
>> with
>>     <Very_Long_Name>'Succ;
>>
>> which would eliminate the potential for errors, possibly generate better
>> code (by not having to evaluate <Very_Long_Name> twice if it contains
>> function calls), and eliminate the hair-brained calls for ":=+" operators
>> (which don't even work for Ada).
>>
>
> Would there be a problem using this?
>
>    Generic
> Type T is (<>);
> with function Succ(Input : T) Return T is T'Succ;
>    package Test is
> -- Body does whatever is needed requiring Very_Long_Name as T.
>    end Test;

I don't see how this would work. You need to be able to use it on multiple 
<Very_Long_Name>s in order to make it worth the effort.

Something like:

    generic
        type T is (<>);
    procedure Succ (Obj : in out T; Count : in Natural := 1) is -- Note: I 
know this requires a separate spec!
    begin
          for I in 1 .. Count loop
              Obj := T'Succ(Obj);
          end loop;
    end Succ;

would match the intended attribute semantically.

But it doesn't help much, because you have to write the generic somewhere, 
and then you have to instantiate it when you need it as well. That's not 
very helpful for what is intended to be a short-cut (you usually would end 
up typing more). The big advantage of an object attribute (like this 'Succ 
or GNAT's 'Img) is that you don't have to figure out the nominal subtype of 
the object to increment it once (which you do to write an instance of my 
Succ generic).

                                         Randy. 





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

* Re: Is this expected behavior or not
  2013-03-14 17:29                                         ` Dmitry A. Kazakov
  2013-03-14 18:16                                           ` Georg Bauhaus
@ 2013-03-14 22:12                                           ` Randy Brukardt
  2013-03-15  9:46                                             ` Dmitry A. Kazakov
       [not found]                                             ` <ewe0v3ck1xdo$.e8rtuof27ke6$.dlg@40tude.net >
  1 sibling, 2 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-03-14 22:12 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1wv3p3nrtejfk$.bwebhg9agt0l.dlg@40tude.net...
> On Thu, 14 Mar 2013 17:21:23 +0100, J-P. Rosen wrote:
...
>> The set of values is not defined by Positive, it is defined by Integer.
>
> Still, Positive has values, and operations.

Yes, and they're exactly the same set as Integer has. The values and 
operations of a type determine what is statically allowed (that is, what is 
legal). And for the purposes of legality, Integer and Positive are exactly 
the same.

There are some differences in *dynamic* behavior, but that has nothing to do 
with the available values and operations. (The text you quoted from the RM 
about values "belonging" to a subtype is defining dynamic behavior.) I 
recall some Dmitry guy telling us that dynamic behavior is different from 
static behavior, and even claiming that dynamic behavior cannot constitute a 
contract. So it if is not a *contract*, how come it matters for a *type* 
(which is an integral part of describing a contract)?

                                                                 Randy.





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

* Re: Is this expected behavior or not
  2013-03-13 17:45                           ` Simon Wright
  2013-03-13 19:37                             ` Dmitry A. Kazakov
@ 2013-03-14 22:41                             ` Florian Weimer
  1 sibling, 0 replies; 242+ messages in thread
From: Florian Weimer @ 2013-03-14 22:41 UTC (permalink / raw)


* Simon Wright:

> I don't remember ever using 'Pred/'Succ, but I'd sorely miss
> 'First/'Last.

Personally, I find it rather odd that array bounds are preserved by
slicing.  This feature doesn't come for free, and leads to slightly
more verbose code without conveying useful information.  On the other
hand, it makes array indexing effectively zero-based, which I find
more natural.



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

* Re: Is this expected behavior or not
  2013-03-14 21:51                                   ` Randy Brukardt
@ 2013-03-15  1:10                                     ` Adam Beneschan
  2013-03-15 21:22                                       ` Randy Brukardt
  2013-03-15  9:20                                     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Adam Beneschan @ 2013-03-15  1:10 UTC (permalink / raw)


On Thursday, March 14, 2013 2:51:11 PM UTC-7, Randy Brukardt wrote:

> No one cares about that. You don't need to know about the laws of  
> thermodynamics to operate a caase,

Are you sure about this?  Personally, I don't know how to operate a caase, and I couldn't find any instructions on the Internet about how to use a caase, or how to repair a caase, or for that matter even what a caase is.  

Sorry--I'm sure this is a typo but I can't figure out what you meant to say.  :)

> and you don't need to know anything about 
> type-algebras or other such baloney to program in a programming language. 
> And it's the use of a programming language - not theories - that determines 
> whether or not the language is truly usable.

To my mind, the only reason to talk about abstract data types at all is that there are practical reasons why it's helpful for programmers to understand and think about them, and those practical reasons have to do with things like reusability, readability, and all that good stuff that helps us write correct programs and keep them correct.  Programming language design involves trying to figure out what concepts, what syntaxes, etc., serve those goals.  I don't see mathematics as being much help with this.  The sciences that would help here seem to be more akin to psychology.

                               -- Adam



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

* Re: Is this expected behavior or not
  2013-03-14 22:01                                   ` Randy Brukardt
@ 2013-03-15  3:27                                     ` Shark8
  2013-03-15 21:05                                       ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-15  3:27 UTC (permalink / raw)


On Thursday, March 14, 2013 4:01:03 PM UTC-6, Randy Brukardt wrote:
> "Shark8" <onewingedshark@gmail.com> wrote in message 
> news:99929f93-b80f-47c3-8a37-c81002733754@googlegroups.com...
> 
> >
> > Would there be a problem using this?
> >    Generic
> > Type T is (<>);
> > with function Succ(Input : T) Return T is T'Succ;
> >    package Test is
> > -- Body does whatever is needed requiring Very_Long_Name as T.
> >    end Test;
> 
> I don't see how this would work. You need to be able to use it on multiple 
> <Very_Long_Name>s in order to make it worth the effort.

Er, wouldn't the function Succ be applicable to all Very_Long_Name items inside the package?

> 
> Something like:
> 
>     generic
>         type T is (<>);
>     procedure Succ (Obj : in out T; Count : in Natural := 1) is -- Note: I 
> know this requires a separate spec!
>     begin
>           for I in 1 .. Count loop
>               Obj := T'Succ(Obj);
>           end loop;
>     end Succ;
> 
> would match the intended attribute semantically.
> 
> 
> But it doesn't help much, because you have to write the generic somewhere, 
> and then you have to instantiate it when you need it as well. That's not 
> very helpful for what is intended to be a short-cut (you usually would end 
> up typing more). The big advantage of an object attribute (like this 'Succ 
> or GNAT's 'Img) is that you don't have to figure out the nominal subtype of 
> the object to increment it once (which you do to write an instance of my 
> Succ generic).

Hm, true; speaking of object-attributes I sometimes [though not too often] wish I could write something like:
 Procedure X( Input : Some_Type ) is
  Temp : Input'Type := Some_Value;
 begin
  -- Whatever needs done.
 end X;

Is there any reason that should be disallowed / would be difficult for compiler-writers to implement?



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

* Re: Is this expected behavior or not
  2013-03-14 21:51                                   ` Randy Brukardt
  2013-03-15  1:10                                     ` Adam Beneschan
@ 2013-03-15  9:20                                     ` Dmitry A. Kazakov
  2013-03-15 21:43                                       ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-15  9:20 UTC (permalink / raw)


On Thu, 14 Mar 2013 16:51:11 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:13y3efy877tjl$.5yuu230sknnq$.dlg@40tude.net...
>> On Wed, 13 Mar 2013 16:01:27 -0500, Randy Brukardt wrote:
>>
>>> You have many interesting ideas that would be far better served if you
>>> described them in Ada-terms.
>>
>> How do you describe tagged types in Ada 83 terms?
> 
> Why would I want to?

You insisted on that claiming that Ada can be only discussed in Ada-terms.

>> RM is not the place where you could do that work. RM is about engineering,
>> not science. You don't describe thermodynamic processes in terms of
>> Volkswagen Owner's Manual. Thermodynamics apply both to VW and GM,
>> regardless whatever manuals.
> 
> No one cares about that.

People building cars do.

>You don't need to know about the laws of 
> thermodynamics to operate a caase,

Until it works as expected, yes. But if you wonder why your car consumes
gas rather than produces it, you should turn to thermodynamics.
 
> Another way to put it is that raw science (as you called it) is essentially 
> irrelevant unless it can be applied to engineering. After all, *ideas* are 
> worthless; only execution has value in today's world. I care about the 
> execution (that is the usability of the design) of Ada, not how it fits into 
> someone's theory of how things should be.

Then you must have wrong understanding of science. It is actually the
reverse: if the theory does not explain facts, it is wrong.

Ada's subtype as defined by RM is a fact to explain (and to predict
consequences of the choices made). The theory does it quite well. The rant
about how Ada's RM names its subtypes is absolutely irrelevant.

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



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

* Re: Is this expected behavior or not
  2013-03-14 18:16                                           ` Georg Bauhaus
@ 2013-03-15  9:33                                             ` Dmitry A. Kazakov
  2013-03-15 10:05                                               ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-15  9:33 UTC (permalink / raw)


On Thu, 14 Mar 2013 19:16:35 +0100, Georg Bauhaus wrote:

> On 14.03.13 18:29, Dmitry A. Kazakov wrote:
>>> > And please, we are talking about Ada here, not KOVOA (Kasakov's Own View
>>> > of Ada).
>> Yes, it is my view of Ada. You have yours. What is wrong with that?
> 
> An analogy:
[...]

You are confusing program with the language of. You can write a program in
OOA/D-way in any language, Assembler included. That does not make those
languages OOPL.

OOA/D /= OOPL

OOPL supports certain kinds of ADT's at the language level. There is no
agreed definition but usually support of dynamic polymorphism (=sets of
ADT's and ADT representing these sets) is considered necessary for a
language to be considered OO.

Ada 95+ is an OOPL according to this definition, because Ada directly
supports sets of types (Ada's class) and has types representing instances
from set members (class-wide types).

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



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

* Re: Is this expected behavior or not
  2013-03-14 22:12                                           ` Randy Brukardt
@ 2013-03-15  9:46                                             ` Dmitry A. Kazakov
       [not found]                                             ` <ewe0v3ck1xdo$.e8rtuof27ke6$.dlg@40tude.net >
  1 sibling, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-15  9:46 UTC (permalink / raw)


On Thu, 14 Mar 2013 17:12:28 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1wv3p3nrtejfk$.bwebhg9agt0l.dlg@40tude.net...
>> On Thu, 14 Mar 2013 17:21:23 +0100, J-P. Rosen wrote:
> ...
>>> The set of values is not defined by Positive, it is defined by Integer.
>>
>> Still, Positive has values, and operations.
> 
> Yes, and they're exactly the same set as Integer has.

Even so, having those makes it an ADT. For the sake of argument consider

   subtype Integer_X is Integer;

Both are ADTs.

BTW, a renaming would be the thing you are talking about. But Ada does not
have type renaming. People [mis]using subtypes for the purpose of renaming
must be prepared to nasty surprises.

> There are some differences in *dynamic* behavior, but that has nothing to do 
> with the available values and operations. (The text you quoted from the RM 
> about values "belonging" to a subtype is defining dynamic behavior.) I 
> recall some Dmitry guy telling us that dynamic behavior is different from 
> static behavior, and even claiming that dynamic behavior cannot constitute a 
> contract. So it if is not a *contract*, how come it matters for a *type* 
> (which is an integral part of describing a contract)?

I don't understand the point you are making. You cannot derive contract
from behavior, simply because it is converse: contract is imposed to
restrain possible behaviors.

You might claim that implied contracts of Integer and Positive are exactly
same. I doubt that many would agree with that.

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



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

* Re: Is this expected behavior or not
  2013-03-15  9:33                                             ` Dmitry A. Kazakov
@ 2013-03-15 10:05                                               ` Georg Bauhaus
  2013-03-15 11:15                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-15 10:05 UTC (permalink / raw)


On 15.03.13 10:33, Dmitry A. Kazakov wrote:
> On Thu, 14 Mar 2013 19:16:35 +0100, Georg Bauhaus wrote:
>
>> On 14.03.13 18:29, Dmitry A. Kazakov wrote:
>>>>> And please, we are talking about Ada here, not KOVOA (Kasakov's Own View
>>>>> of Ada).
>>> Yes, it is my view of Ada. You have yours. What is wrong with that?
>>
>> An analogy:
> [...]
>
> You are confusing program with the language of.

I did chose this confused view to demonstrate what will be the
effect of confusing subtype constraints (or not, as in 'Succ)
and types in the sense everyone here is supposed to approach
the word "type". Except when indicated.

Ada is then not a typed LSP language at the level of subtype constraints
and attributes of types. Make it such a language, make it convincing,
and define a model that can be turned into Ada language definitions.

But, please, mark those phrases that say "problem" as "problem
if 'Succ is viewed as a function that is different from how it
is defined" in the universe of c.l.ada, but could be defined
if 'Succ were an operation of a subtype turned ADT (which it
isn't, in Ada).

> OOPL supports certain kinds of ADT's at the language level.

Right. At the language level,
Ada does not support certain kinds of LSP at the subtype level (well),
Ada does not support equating types and subtypes, and
Ada does not support equating ADTs and type with all attributes.

Because type /= subtype, here, at the language level.

That's why I had chosen the OOP view of C. It's not an OOP
at the language level.





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

* Re: Is this expected behavior or not
  2013-03-15 10:05                                               ` Georg Bauhaus
@ 2013-03-15 11:15                                                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-15 11:15 UTC (permalink / raw)


On Fri, 15 Mar 2013 11:05:39 +0100, Georg Bauhaus wrote:

> I did chose this confused view to demonstrate what will be the
> effect of confusing subtype constraints (or not, as in 'Succ)
> and types in the sense everyone here is supposed to approach
> the word "type". Except when indicated.

I already addressed this. When type+constraint is not considered a type
the language becomes weakly typed.

Note also that any language, even untyped, can be attributed with types.
And programmers think in terms of types even if the language does not allow
to articulate these types in language terms.

Ada's strength, e.g. comparing to C, is in allowing to articulate types and
their relationships (e.g. subtypes) rather than leaving them to reader's
imagination.

> Ada is then not a typed LSP language at the level of subtype constraints
> and attributes of types. Make it such a language, make it convincing,
> and define a model that can be turned into Ada language definitions.

You are confusing LSP with typing. LSP is much less than typing in general.
Ada subtype is not an LSP-subtype, yet both Ada- and LSP-subtypes are
types.

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



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

* Re: Is this expected behavior or not
  2013-03-15  3:27                                     ` Shark8
@ 2013-03-15 21:05                                       ` Randy Brukardt
  2013-03-15 21:46                                         ` Robert A Duff
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-15 21:05 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:87ec4b1d-f7cd-49a4-8cff-d44aeb76a1ad@googlegroups.com...
...
> Hm, true; speaking of object-attributes I sometimes [though not too often] 
> wish I could write something like:
> Procedure X( Input : Some_Type ) is
>  Temp : Input'Type := Some_Value;
> begin
>  -- Whatever needs done.
> end X;
>
> Is there any reason that should be disallowed / would be difficult for 
> compiler-writers to implement?

I've occassionally had such a thought, too. Probably the reason this doesn't 
exist is that Ada 83 didn't have type-valued attributes and thus it wasn't 
considered there. ('Base could only be used as an attribute prefix in Ada 
83). There would potentially be a cost to an object attribute vs. using the 
subtype name directly, in that the prefix would have to be evaluated (which, 
if it included function calls or checks, would generate some code).

I suppose there might be a problem in that this would provide a way to give 
a name to anonymous types. Most of the Ada rules presume that such types 
can't be named and thus can't be used in contexts where a name is required 
(like explicit type conversions). So there might be some problems raised by 
that; probably not insurmountable but makes it harder than trivial (in which 
case all of the trade-offs have to be considered - and given that the new 
capability here is either low or not desired - depending on your point of 
view - that makes it unlikely).

What I'm talking about is something like:

   procedure P (A : access Int) is
      Obj : A'Type; -- A second object of a single anonymous type, not 
possible now.
   begin
      Obj := A'Type(Some_Ptr); -- An explicit conversion to an anonymous 
access type, not possible now.
   end P;

It's not clear that there is any problem here, it's just that we haven't 
considered it and usually that means there is a problem there. :-) Could 
just be FUD, too.

                                              Randy.





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

* Re: Is this expected behavior or not
       [not found]                                             ` <ewe0v3ck1xdo$.e8rtuof27ke6$.dlg@40tude.net >
@ 2013-03-15 21:17                                               ` Randy Brukardt
  2013-03-16  7:51                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-15 21:17 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:ewe0v3ck1xdo$.e8rtuof27ke6$.dlg@40tude.net...
> On Thu, 14 Mar 2013 17:12:28 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1wv3p3nrtejfk$.bwebhg9agt0l.dlg@40tude.net...
>>> On Thu, 14 Mar 2013 17:21:23 +0100, J-P. Rosen wrote:
>> ...
>>>> The set of values is not defined by Positive, it is defined by Integer.
>>>
>>> Still, Positive has values, and operations.
>>
>> Yes, and they're exactly the same set as Integer has.
>
> Even so, having those makes it an ADT. For the sake of argument consider
>
>   subtype Integer_X is Integer;
>
> Both are ADTs.
>
> BTW, a renaming would be the thing you are talking about. But Ada does not
> have type renaming. People [mis]using subtypes for the purpose of renaming
> must be prepared to nasty surprises.
>
>> There are some differences in *dynamic* behavior, but that has nothing to 
>> do
>> with the available values and operations. (The text you quoted from the 
>> RM
>> about values "belonging" to a subtype is defining dynamic behavior.) I
>> recall some Dmitry guy telling us that dynamic behavior is different from
>> static behavior, and even claiming that dynamic behavior cannot 
>> constitute a
>> contract. So it if is not a *contract*, how come it matters for a *type*
>> (which is an integral part of describing a contract)?
>
> I don't understand the point you are making. You cannot derive contract
> from behavior, simply because it is converse: contract is imposed to
> restrain possible behaviors.
>
> You might claim that implied contracts of Integer and Positive are exactly
> same. I doubt that many would agree with that.

I certainly wouldn't, because *I* consider the dynamic behavior to be part 
of the contract. But, clearly, you don't (and you've indicated that above 
again. So yes, given your world view, the contracts of Integer and Positive 
are exactly the same. That's clear, because they're interchangable in terms 
of legality and resolution (anything having to do with compile-time 
checking). The quote above says that you disagree with yourself. :-)

"I doubt that many would agree with that." That's certainly true, but that's 
because few would agree with you on the notion that the contract does not 
include the dynamic behavior. In any case, either *you* have to agree with 
this premise (and thus all of your arguments on type vs. subtypes are 
nonsense), or you are no longer agreeing with your previous statements about 
contracts (which I for one would welcome, but it's seems pretty unlikely of 
a change).

I'm sure you'll try to reconcile this by completely ignoring the rules of 
Ada and redefining all of the terms involved. Enjoy.

                                     Randy.





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

* Re: Is this expected behavior or not
  2013-03-15  1:10                                     ` Adam Beneschan
@ 2013-03-15 21:22                                       ` Randy Brukardt
  0 siblings, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-03-15 21:22 UTC (permalink / raw)


"Adam Beneschan" <adam@irvine.com> wrote in message 
news:927dfd51-e4b1-45af-9d51-57c167e84890@googlegroups.com...
>On Thursday, March 14, 2013 2:51:11 PM UTC-7, Randy Brukardt wrote:
>
>> No one cares about that. You don't need to know about the laws of
>> thermodynamics to operate a caase,
>
>Are you sure about this?  Personally, I don't know how to operate a caase, 
>and I couldn't find any instructions on the >Internet about how to use a 
>caase, or how to repair a caase, or for that matter even what a caase is.
>
>Sorry--I'm sure this is a typo but I can't figure out what you meant to 
>say.  :)

The word was "car", and how it turned into "caase" will be an enduring 
mystery.

>> and you don't need to know anything about
>> type-algebras or other such baloney to program in a programming language.
>> And it's the use of a programming language - not theories - that 
>> determines
>> whether or not the language is truly usable.

>To my mind, the only reason to talk about abstract data types at all is 
>that there are practical reasons
>why it's helpful for programmers to understand and think about them, and 
>those practical reasons have
>to do with things like reusability, readability, and all that good stuff 
>that helps us write correct programs
>and keep them correct.  Programming language design involves trying to 
>figure out what concepts, what
>syntaxes, etc., serve those goals.  I don't see mathematics as being much 
>help with this.  The sciences
>that would help here seem to be more akin to psychology.

Exactly. Thanks for expanding on my point. Too many languages are designed 
based on theory rather than usability. Theory might be useful for academics 
to classify languages, but that's about it (and the value of that exercise 
is dubious).

                                   Randy.





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

* Re: Is this expected behavior or not
  2013-03-15  9:20                                     ` Dmitry A. Kazakov
@ 2013-03-15 21:43                                       ` Randy Brukardt
  2013-03-16  7:56                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-15 21:43 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1xsmzl7alqflb$.oz1qkrleisa7$.dlg@40tude.net...
> On Thu, 14 Mar 2013 16:51:11 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:13y3efy877tjl$.5yuu230sknnq$.dlg@40tude.net...
>>> On Wed, 13 Mar 2013 16:01:27 -0500, Randy Brukardt wrote:
>>>
>>>> You have many interesting ideas that would be far better served if you
>>>> described them in Ada-terms.
>>>
>>> How do you describe tagged types in Ada 83 terms?
>>
>> Why would I want to?
>
> You insisted on that claiming that Ada can be only discussed in Ada-terms.

You didn't answer the question. Why would you want to describe something 
from a recent version of the language in terms of an obsolete one? On top of 
which, when anyone says Ada without qualification, that means Ada 2012 (as 
that is the current version of Ada). I'm not likely to talk about Ada 83 as 
there is no point (of course, for many things, the language version doesn't 
matter).

...
>> Another way to put it is that raw science (as you called it) is 
>> essentially
>> irrelevant unless it can be applied to engineering. After all, *ideas* 
>> are
>> worthless; only execution has value in today's world. I care about the
>> execution (that is the usability of the design) of Ada, not how it fits 
>> into
>> someone's theory of how things should be.
>
> Then you must have wrong understanding of science. It is actually the
> reverse: if the theory does not explain facts, it is wrong.

Huh? I'm contending that the theory is irrelevant (much like religion -- and 
it shares a lot of characteristics with that). That's because you can't use 
it to design a useful programming language, only to pigeon-hole and/or take 
potshots at it after the fact. That's not useful or helpful.

One could say that about a lot of basic theories. Knowledge of 
thermodynamics has little to do with designing an engine; you need a lot of 
knowledge about other things to do that, and thermodynamics is *way* down on 
the list of things that matter. After all those rules are very simple to 
paraphrase: "You can't win the game. You can't break even. And you can't 
quit the game." And you can't do much even knowing that.

> Ada's subtype as defined by RM is a fact to explain (and to predict
> consequences of the choices made). The theory does it quite well. The rant
> about how Ada's RM names its subtypes is absolutely irrelevant.

But no one cares, because such matching has no relevance to anything: it's 
not going to change the design of Ada (compatibility concerns would prevent 
that in any case) and nothing about it would help you be a better Ada 
programmer (especially as the terminology clash makes it close to impossible 
to think about one and make sense of the other). So it is a waste of time.

                                      Randy.





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

* Re: Is this expected behavior or not
  2013-03-15 21:05                                       ` Randy Brukardt
@ 2013-03-15 21:46                                         ` Robert A Duff
  2013-03-16  5:52                                           ` Shark8
  2013-03-16  9:29                                           ` Georg Bauhaus
  0 siblings, 2 replies; 242+ messages in thread
From: Robert A Duff @ 2013-03-15 21:46 UTC (permalink / raw)


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

> "Shark8" <onewingedshark@gmail.com> wrote in message 
> news:87ec4b1d-f7cd-49a4-8cff-d44aeb76a1ad@googlegroups.com...
> ...
>> Hm, true; speaking of object-attributes I sometimes [though not too often]
>> wish I could write something like:
>> Procedure X( Input : Some_Type ) is
>>  Temp : Input'Type := Some_Value;
>> begin
>>  -- Whatever needs done.
>> end X;
>>
>> Is there any reason that should be disallowed / would be difficult for 
>> compiler-writers to implement?
>
> I've occassionally had such a thought, too.

Me, too.  (I also agree with Shark8's "not too often" comment.)

Many languages allow the type of an object to be deduced from
its initial value.  I believe C++ recently added that feature,
using the "auto" keyword (which it inherited from C, and meant
something completely different -- and completely useless).
Ada allows that in a small way -- named numbers.

>... Probably the reason this doesn't 
> exist is that Ada 83 didn't have type-valued attributes and thus it wasn't 
> considered there.

I suspect the reason was that the designers of Ada 83 thought that
types of things ought to be explicit.  Except for named numbers --
consistency wasn't their strong suit.

> 83). There would potentially be a cost to an object attribute vs. using the
> subtype name directly, in that the prefix would have to be evaluated (which,
> if it included function calls or checks, would generate some code).

Such cases could be forbidden.

Or one could do something like what C does for sizeof -- the operand
is not evaluated.  It's as if you could say "X.all'Size" in Ada and
not get a C_E, even if X = null.  That works in C because all sizes
are known at compile time.  In Ada, all types are known at compile
time, so "X.all'Type" (or "X.all'Subtype"?) could conceivably denote
Integer even when X = null.

> It's not clear that there is any problem here, it's just that we haven't 
> considered it and usually that means there is a problem there. :-) Could 
> just be FUD, too.

Well, a bit of FUD is often appropriate in language design.  ;-)

- Bob



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

* Re: Is this expected behavior or not
  2013-03-15 21:46                                         ` Robert A Duff
@ 2013-03-16  5:52                                           ` Shark8
  2013-03-16  7:41                                             ` Dmitry A. Kazakov
  2013-03-16 20:45                                             ` Robert A Duff
  2013-03-16  9:29                                           ` Georg Bauhaus
  1 sibling, 2 replies; 242+ messages in thread
From: Shark8 @ 2013-03-16  5:52 UTC (permalink / raw)


On Friday, March 15, 2013 3:46:26 PM UTC-6, Robert A Duff wrote:
> "Randy Brukardt" <randy@rrsoftware.com> writes:
> 
> > "Shark8" <onewingedshark@gmail.com> wrote in message 
> > news:87ec4b1d-f7cd-49a4-8cff-d44aeb76a1ad@googlegroups.com...
> > ...
> >> Hm, true; speaking of object-attributes I sometimes [though not too often]
> >> wish I could write something like:
> >> Procedure X( Input : Some_Type ) is
> >>  Temp : Input'Type := Some_Value;
> >> begin
> >>  -- Whatever needs done.
> >> end X;
> >>
> >> Is there any reason that should be disallowed / would be difficult for 
> >> compiler-writers to implement?
> >
> > I've occassionally had such a thought, too.
> 
> Me, too.  (I also agree with Shark8's "not too often" comment.)
> 
> 
> Many languages allow the type of an object to be deduced from
> its initial value.  I believe C++ recently added that feature,
> using the "auto" keyword (which it inherited from C, and meant
> something completely different -- and completely useless).
> Ada allows that in a small way -- named numbers.

This isn't _quite_ the same, it's declaring an object to be of the same type as some other (and already known) object.

> >... Probably the reason this doesn't 
> > exist is that Ada 83 didn't have type-valued attributes and thus it wasn't 
> > considered there.
> 
> I suspect the reason was that the designers of Ada 83 thought that
> types of things ought to be explicit.  Except for named numbers --
> consistency wasn't their strong suit.

I thought that named numbers were of the Universal_Integer (if integral) or Universal_Float_and_Fixed if not... of course that could just be an incorrect notion I've developed.

> 
> > 83). There would potentially be a cost to an object attribute vs. using the
> > subtype name directly, in that the prefix would have to be evaluated (which,
> > if it included function calls or checks, would generate some code).
> 
> Such cases could be forbidden.

True; but there could be some more interesting cases, say, for Ada 2020.
Something like:


Abstract Type UNIVERSAL_STRING(Element : UNIVERSAL_CHARACTER) is 
    Array(Positive Range <>) of Element'Type;

{Or something similar; if we did that we could conceivably be able to fold Strings, Wide_Strings, and Wide_Wide_Strings together having those packages in essence become instances of a GENERIC_STRING package... it would likely have a monstrous amount of parameters, for functions like To_Upper and To_Lower.}


> > It's not clear that there is any problem here, it's just that we haven't 
> > considered it and usually that means there is a problem there. :-) Could 
> > just be FUD, too.
> 
> Well, a bit of FUD is often appropriate in language design.  ;-)

This is very true; though given the haphazard approach some languages have to design *cough*PHP*cough* one might be tempted to think there's no thought given to design at all.



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

* Re: Is this expected behavior or not
  2013-03-16  5:52                                           ` Shark8
@ 2013-03-16  7:41                                             ` Dmitry A. Kazakov
  2013-03-16 16:55                                               ` Shark8
  2013-03-16 20:45                                             ` Robert A Duff
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-16  7:41 UTC (permalink / raw)


On Fri, 15 Mar 2013 22:52:02 -0700 (PDT), Shark8 wrote:

> True; but there could be some more interesting cases, say, for Ada 2020.
> Something like:
> 
> Abstract Type UNIVERSAL_STRING(Element : UNIVERSAL_CHARACTER) is 
>     Array(Positive Range <>) of Element'Type;

That would not work. I presume that here you want to create a root type for
the class of string types and get at the members of the class (specific
types like Wide_String) using a constraint. The problem is that string
types must have different representations. The mechanism of constraining
does not support. Thus either subtypes will have same representation or you
won't have a class. Another problem is that string types must have more
than one interface to deal with UTF-8 etc. An UTF-8 string is *both* an
array of Wide_Wide_Character (= Unicode code points) and an array or
sequence of Character (octets). An UTF-16 string is an array of
Wide_Wide_Character and an array of Wide_String.
 
-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Is this expected behavior or not
  2013-03-15 21:17                                               ` Randy Brukardt
@ 2013-03-16  7:51                                                 ` Dmitry A. Kazakov
  2013-03-16  9:30                                                   ` Georg Bauhaus
  2013-03-18 22:36                                                   ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-16  7:51 UTC (permalink / raw)


On Fri, 15 Mar 2013 16:17:11 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:ewe0v3ck1xdo$.e8rtuof27ke6$.dlg@40tude.net...
>> On Thu, 14 Mar 2013 17:12:28 -0500, Randy Brukardt wrote:
>>
>>> There are some differences in *dynamic* behavior, but that has nothing to do
>>> with the available values and operations. (The text you quoted from the RM
>>> about values "belonging" to a subtype is defining dynamic behavior.) I
>>> recall some Dmitry guy telling us that dynamic behavior is different from
>>> static behavior, and even claiming that dynamic behavior cannot constitute a
>>> contract. So it if is not a *contract*, how come it matters for a *type*
>>> (which is an integral part of describing a contract)?
>>
>> I don't understand the point you are making. You cannot derive contract
>> from behavior, simply because it is converse: contract is imposed to
>> restrain possible behaviors.
>>
>> You might claim that implied contracts of Integer and Positive are exactly
>> same. I doubt that many would agree with that.
> 
> I certainly wouldn't, because *I* consider the dynamic behavior to be part 
> of the contract. But, clearly, you don't (and you've indicated that above 
> again. So yes, given your world view, the contracts of Integer and Positive 
> are exactly the same. That's clear, because they're interchangable in terms 
> of legality and resolution (anything having to do with compile-time 
> checking). The quote above says that you disagree with yourself. :-)

That would be a consequence of considering them same type. I already said,
that this a path towards weak typing.

But I don't see where I disagree with myself. Contract /= type. You can
have same contract and different types. What about:

   type Same is new Integer;

You also can have different contracts put on the same type in different
contexts. You can have contracts on something that does not involve types
at all. Anyway, I fail to see how contracts are relevant here.

> "I doubt that many would agree with that." That's certainly true, but that's 
> because few would agree with you on the notion that the contract does not 
> include the dynamic behavior. In any case, either *you* have to agree with 
> this premise (and thus all of your arguments on type vs. subtypes are 
> nonsense), or you are no longer agreeing with your previous statements about 
> contracts (which I for one would welcome, but it's seems pretty unlikely of 
> a change).

I don't see why. How *any* contract could make something like Positive a
non-type? There is not many possibilities:

A. Positive is not a type. This is what Georg says. I have no idea what
this is supposed to mean. That 123 is not Positive, or that "+" is not
applied to positives? He escapes into some kind of vague philosophy each
time I ask.

B. Positive is a type. The type is Integer. So Positive = Integer. This is
evidently wrong because there exist programs which semantics sufficiently
change when 'Integer' is replaced by 'Positive'. If the language treats
them same, worse to the language. Luckily Ada checks if Positive is indeed
positive (well, not always, but almost).

C. not (A or B) = my point.

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



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

* Re: Is this expected behavior or not
  2013-03-15 21:43                                       ` Randy Brukardt
@ 2013-03-16  7:56                                         ` Dmitry A. Kazakov
  2013-03-18 22:52                                           ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-16  7:56 UTC (permalink / raw)


On Fri, 15 Mar 2013 16:43:47 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1xsmzl7alqflb$.oz1qkrleisa7$.dlg@40tude.net...
>> On Thu, 14 Mar 2013 16:51:11 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:13y3efy877tjl$.5yuu230sknnq$.dlg@40tude.net...
>>>> On Wed, 13 Mar 2013 16:01:27 -0500, Randy Brukardt wrote:
>>>>
>>>>> You have many interesting ideas that would be far better served if you
>>>>> described them in Ada-terms.
>>>>
>>>> How do you describe tagged types in Ada 83 terms?
>>>
>>> Why would I want to?
>>
>> You insisted on that claiming that Ada can be only discussed in Ada-terms.
> 
> You didn't answer the question. Why would you want to describe something 
> from a recent version of the language in terms of an obsolete one?

To illustrate the point that one cannot extend/modify the language
discussing it in its terms, like baron Munchausen pulling yourself out of a
swamp by your hair.

How would you tell yourself from year 1992 about Ada 95? The other you
would not listen to you.

>>> Another way to put it is that raw science (as you called it) is essentially
>>> irrelevant unless it can be applied to engineering. After all, *ideas* are
>>> worthless; only execution has value in today's world. I care about the
>>> execution (that is the usability of the design) of Ada, not how it fits into
>>> someone's theory of how things should be.
>>
>> Then you must have wrong understanding of science. It is actually the
>> reverse: if the theory does not explain facts, it is wrong.
> 
> Huh? I'm contending that the theory is irrelevant (much like religion -- and 
> it shares a lot of characteristics with that). That's because you can't use 
> it to design a useful programming language, only to pigeon-hole and/or take 
> potshots at it after the fact. That's not useful or helpful.
> 
> One could say that about a lot of basic theories. Knowledge of 
> thermodynamics has little to do with designing an engine; you need a lot of 
> knowledge about other things to do that, and thermodynamics is *way* down on 
> the list of things that matter.

Not at all. Other things are relevant only in the context of more
fundamental laws like thermodynamics. In engineering you must know, at
least in theory, how to deduce any specialized rule from fundamental laws.
This is what differentiates proper science and engineering from junk like
economics or climatology. Granted, CS is somewhere in between.

>> Ada's subtype as defined by RM is a fact to explain (and to predict
>> consequences of the choices made). The theory does it quite well. The rant
>> about how Ada's RM names its subtypes is absolutely irrelevant.
> 
> But no one cares, because such matching has no relevance to anything: it's 
> not going to change the design of Ada (compatibility concerns would prevent 
> that in any case)

There is no compatibility concerns. Robert said in this thread that
Prime'Range, Prime'First, Prime'Last are all illegal. So it is already
incompatible, if under compatibility you understand that a subtype must
inherit everything.

> and nothing about it would help you be a better Ada 
> programmer (especially as the terminology clash makes it close to impossible 
> to think about one and make sense of the other).

On the contrary, understanding that a subtype is a type with values and
operation helps a lot. Especially when it comes to aberrations like with
Prime'Succ. It is an operation of Prime and the programmer should know that
in Ada he has no influence on its implementation which is always inherited
from the base type. If that does not correspond his intent he must change
the design and use other means, e.g. tagged types or unrelated types
(derive Prime privately).

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



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

* Re: Is this expected behavior or not
  2013-03-15 21:46                                         ` Robert A Duff
  2013-03-16  5:52                                           ` Shark8
@ 2013-03-16  9:29                                           ` Georg Bauhaus
  2013-03-16 20:49                                             ` Robert A Duff
  1 sibling, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-16  9:29 UTC (permalink / raw)


On 15.03.13 22:46, Robert A Duff wrote:
> That works in C because all sizes
> are known at compile time.

That's true in C89, but C99 makes sizeof an execution
time operator for variable length arrays. The operand
is then evaluated.

6.5.3.4 has this example,

#include <stddef.h>

size_t fsize3(int n)
{
   char b[n+3];     // variable length array
   return sizeof b; // execution time sizeof
}




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

* Re: Is this expected behavior or not
  2013-03-16  7:51                                                 ` Dmitry A. Kazakov
@ 2013-03-16  9:30                                                   ` Georg Bauhaus
  2013-03-16 10:27                                                     ` Dmitry A. Kazakov
  2013-03-18 22:36                                                   ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-16  9:30 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote:
> On Fri, 15 Mar 2013 16:17:11 -0500, Randy Brukardt wrote:

>> "I doubt that many would agree with that." That's certainly true, but that's 
>> because few would agree with you on the notion that the contract does not 
>> include the dynamic behavior. In any case, either *you* have to agree with 
>> this premise (and thus all of your arguments on type vs. subtypes are 
>> nonsense), or you are no longer agreeing with your previous statements about 
>> contracts (which I for one would welcome, but it's seems pretty unlikely of 
>> a change).
> 
> I don't see why. How *any* contract could make something like Positive a
> non-type?

Sounds like begging the question, to me.

And "contract" adds another source of lexical ambiguities.

> A. Positive is not a type. This is what Georg says. I have no idea what
> this is supposed to mean.

It means what the RM says it means. The RM also says that
'Succ is invariant. *If* someone expects 'Succ to be what it
is not, then the RM says why. The KOVOA theory does
not, cannot, resolve the issue, else we would have seen a new
draft of section 3?

Subtype constraints are "weak" because in some contexts
that seemed what was needed.



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

* Re: Is this expected behavior or not
  2013-03-16  9:30                                                   ` Georg Bauhaus
@ 2013-03-16 10:27                                                     ` Dmitry A. Kazakov
  2013-03-16 11:37                                                       ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-16 10:27 UTC (permalink / raw)


On 16 Mar 2013 09:30:29 GMT, Georg Bauhaus wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote:
>> On Fri, 15 Mar 2013 16:17:11 -0500, Randy Brukardt wrote:
> 
>>> "I doubt that many would agree with that." That's certainly true, but that's 
>>> because few would agree with you on the notion that the contract does not 
>>> include the dynamic behavior. In any case, either *you* have to agree with 
>>> this premise (and thus all of your arguments on type vs. subtypes are 
>>> nonsense), or you are no longer agreeing with your previous statements about 
>>> contracts (which I for one would welcome, but it's seems pretty unlikely of 
>>> a change).
>> 
>> I don't see why. How *any* contract could make something like Positive a
>> non-type?
> 
> Sounds like begging the question, to me.
> 
> And "contract" adds another source of lexical ambiguities.

Source of lexical ambiguities? This sounds like an encoding problem.
Something wrong with your file system?

>> A. Positive is not a type. This is what Georg says. I have no idea what
>> this is supposed to mean.
> 
> It means what the RM says it means.

Which is?

> Subtype constraints are "weak" because in some contexts
> that seemed what was needed.

You read that from the RM?

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



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

* Re: Is this expected behavior or not
  2013-03-16 10:27                                                     ` Dmitry A. Kazakov
@ 2013-03-16 11:37                                                       ` Georg Bauhaus
  2013-03-16 13:04                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-16 11:37 UTC (permalink / raw)


On 16.03.13 11:27, Dmitry A. Kazakov wrote:

>> And "contract" adds another source of lexical ambiguities.
>
> Source of lexical ambiguities? This sounds like an encoding problem.

It is a problem of semantics. Discussions ignited by a lack of definitions
that will unambiguously assign meaning to "contract".

>>> A. Positive is not a type. This is what Georg says. I have no idea what
>>> this is supposed to mean.
>>
>> It means what the RM says it means.
>
> Which is?

Randy said, in <khqpfb$b21$1@munin.nbi.dk>:
"the quote you [Dmitry] made from the RM says as much."

Positive is a KOVOA-type; Positive is a type-together-with in the
Ada 83 Rationale; the type of Positive is not Positive by the LRM.
"Is-a" and "is-not" are thus a contradiction if and only if one
mixes contexts. There are three contexts above. We have to decide
which context applies to 'Succ in an Ada program governed by the LRM.
For problems of using the language, I choose the language's RM.

I trust there is interest in a KOVOA draft of section 3, proposed
to Ada-Comment.

>> Subtype constraints are "weak" because in some contexts
>> that seemed what was needed.
>
> You read that from the RM?

I read what the inventor of the subtype, Ivan Godard, has had to say.
http://newsgroups.derkeiler.com/Archive/Comp/comp.arch/2012-08/msg00360.html




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

* Re: Is this expected behavior or not
  2013-03-16 11:37                                                       ` Georg Bauhaus
@ 2013-03-16 13:04                                                         ` Dmitry A. Kazakov
  2013-03-16 16:10                                                           ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-16 13:04 UTC (permalink / raw)


On Sat, 16 Mar 2013 12:37:33 +0100, Georg Bauhaus wrote:

> On 16.03.13 11:27, Dmitry A. Kazakov wrote:
> 
>>> And "contract" adds another source of lexical ambiguities.
>>
>> Source of lexical ambiguities? This sounds like an encoding problem.
> 
> It is a problem of semantics.

A problem of semantics is lexical ambiguity...?

>>>> A. Positive is not a type. This is what Georg says. I have no idea what
>>>> this is supposed to mean.
>>>
>>> It means what the RM says it means.
>>
>> Which is?

[...]
Why don't you simply explain why in your opinion Positive is not a type?
Without lexical ambiguities, semantic problems and other smoke and mirrors
stuff.

>>> Subtype constraints are "weak" because in some contexts
>>> that seemed what was needed.
>>
>> You read that from the RM?
> 
> I read what the inventor of the subtype, Ivan Godard, has had to say.
> http://newsgroups.derkeiler.com/Archive/Comp/comp.arch/2012-08/msg00360.html

To paraphrase Omar: if those books are in agreement with the RM, we have no
need of them; and if these are opposed to the RM, destroy them. (:-))

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



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

* Re: Is this expected behavior or not
  2013-03-16 13:04                                                         ` Dmitry A. Kazakov
@ 2013-03-16 16:10                                                           ` Georg Bauhaus
  2013-03-16 17:47                                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-16 16:10 UTC (permalink / raw)


On 16.03.13 14:04, Dmitry A. Kazakov wrote:
> On Sat, 16 Mar 2013 12:37:33 +0100, Georg Bauhaus wrote:
>
>> On 16.03.13 11:27, Dmitry A. Kazakov wrote:
>>
>>>> And "contract" adds another source of lexical ambiguities.
>>>
>>> Source of lexical ambiguities? This sounds like an encoding problem.
>>
>> It is a problem of semantics.
>
> A problem of semantics is lexical ambiguity...?

Lexical ambiguity as in "This word can be understood in two or more
different ways".  The word "contract" is of this kind, which is one
cause of heated debate.


> Why don't you simply explain why in your opinion Positive is not a type?

Whether or not Positive'Succ *is* invariant depends solely on definitions
of Ada, not on my opinion. Whether or not 'Succ *should* become something
else in order for a certain kind of types-with-predicates to work has been,
and is an interesting question. It is not satisfactorily answered, though,
by saying the what *is* is not what it is but claiming that it is what it
*should* be (algebraic "sub-types", inheritance, whatever). It isn't (both
senses).


> To paraphrase Omar: if those books are in agreement with the RM, we have no
> need of them; and if these are opposed to the RM, destroy them. (:-))

I only asked that words should be marked as referring to Ada or to something else.




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

* Re: Is this expected behavior or not
  2013-03-16  7:41                                             ` Dmitry A. Kazakov
@ 2013-03-16 16:55                                               ` Shark8
  2013-03-16 17:36                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-16 16:55 UTC (permalink / raw)
  Cc: mailbox

On Saturday, March 16, 2013 1:41:27 AM UTC-6, Dmitry A. Kazakov wrote:
> On Fri, 15 Mar 2013 22:52:02 -0700 (PDT), Shark8 wrote:
> 
> > True; but there could be some more interesting cases, say, for Ada 2020.
> > Something like:
> > 
> > Abstract Type UNIVERSAL_STRING(Element : UNIVERSAL_CHARACTER) is 
> >     Array(Positive Range <>) of Element'Type;
> 
> That would not work. I presume that here you want to create a root type for
> the class of string types and get at the members of the class (specific
> types like Wide_String) using a constraint. The problem is that string
> types must have different representations. The mechanism of constraining
> does not support. 

Kind of, but not really; I'm thinking a sort of combination of generics and classes (in the general sense, not the OOP-sense): a way to specify a general behavior for a type-class. (i.e. having the ability to fully-specify things like attributes [not really shown in this example].)

> Thus either subtypes will have same representation or you
> won't have a class.

I'm thinking of it more in the terms of generic operations: independent of representation.

> Another problem is that string types must have more 
> than one interface to deal with UTF-8 etc. An UTF-8 string is *both* an
> array of Wide_Wide_Character (= Unicode code points) and an array or
> sequence of Character (octets).

Ah, things get tricky here; Unicode is kind of a bear when you consider 'characters' because its codepoints aren't necessarily characters. An example would be the so-called "combining characters" which you can use for things like accents or ZALGO-text. (See these, respectively: http://en.wikipedia.org/wiki/Combining_character and, http://eeemo.net/ )

An important implication of this is that string search/manipulation becomes MUCH more complex. (`+a = à) means that you now have to search for multiple possibilities when your target is "à" -> the single-glyph code-point, or the combining-character points... and that's not taking into consideration whether you should consider a & à & (a+diacritic) to be the same or unique entities -- and casing is another combinatorial factor.

It would be a big mistake to assume character = code-point when dealing with Unicode.

> An UTF-16 string is an array of Wide_Wide_Character and an array of Wide_String.

UTF-16 is perhaps the worst possible encoding you can have for Unicode. With UTF-8 you don't need to worry about byte-order (everything's sequential) and with UTF-32 you don't need to decode the information (each element *IS* a code-point)... but UTF-16 offers neither of these.

------------------------------------------------------

I guess what I'm trying to say is that if we did it right, we could modify/expand the type-system so that something like UNIVERSAL_INTEGER could be made/explicitly-specified. (And if done extremely well, something like UNIVERSAL_STRING where perhaps the only thing differentiating the strings would be the 'instantiation' with their proper character-type* and manipulation-functions.) -- GNAT already has the 'Universal_Literal_String which works in either of the following lines:

Ada.Wide_Wide_Text_IO.Put_Line( Ada.Numerics.Pi'Universal_Literal_String )
Ada.Text_IO.Put_Line( Ada.Numerics.Pi'Universal_Literal_String )

In any case; I think it worth considering not just outward/downward expansion of the language, but inward/upward [unification] as well.



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

* Re: Is this expected behavior or not
  2013-03-16 16:55                                               ` Shark8
@ 2013-03-16 17:36                                                 ` Dmitry A. Kazakov
  2013-03-16 21:51                                                   ` Shark8
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-16 17:36 UTC (permalink / raw)


On Sat, 16 Mar 2013 09:55:53 -0700 (PDT), Shark8 wrote:

> On Saturday, March 16, 2013 1:41:27 AM UTC-6, Dmitry A. Kazakov wrote:
>> 
>> Thus either subtypes will have same representation or you
>> won't have a class.
> 
> I'm thinking of it more in the terms of generic operations: independent of
> representation.

Generics are useless for strings [and almost anything else]. Without
class-wide objects you need a set of instances for each combination of
encoding/character/index. No better than present mess.
 
 >> Another problem is that string types must have more 
>> than one interface to deal with UTF-8 etc. An UTF-8 string is *both* an
>> array of Wide_Wide_Character (= Unicode code points) and an array or
>> sequence of Character (octets).
> 
> Ah, things get tricky here; Unicode is kind of a bear when you consider
> 'characters' because its codepoints aren't necessarily characters.

Yes, code points are glyphs.

> An
> example would be the so-called "combining characters" which you can use
> for things like accents or ZALGO-text. (See these, respectively:
> http://en.wikipedia.org/wiki/Combining_character and, http://eeemo.net/ )

It is important for rendering only, if anybody uses it.
 
> It would be a big mistake to assume character = code-point when dealing
> with Unicode.
[...]

Rules according to which two texts are considered equivalent can be
infinitely complex. You cannot do that on the basis of per character
comparison. Character = glyph = code point is good enough for most
applications.
 
> I guess what I'm trying to say is that if we did it right, we could
> modify/expand the type-system so that something like UNIVERSAL_INTEGER
> could be made/explicitly-specified.

Arrays must have interfaces. Array interface should vary along the index
and element "axes" forming a class. Any type should have a class. It should
be possible to drop implementation upon inheritance composing operations
with type conversion. That is basically all. It would be fully backward
compatible. Actual problems lie elsewhere [MD, parallel type hierarchies].

> In any case; I think it worth considering not just outward/downward
> expansion of the language, but inward/upward [unification] as well.

Welcome in the club. But in order to be able to weight proposals you need a
more or less formal framework to describe language type system. Already
this little faces a fierce opposition. So don't expect much.

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



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

* Re: Is this expected behavior or not
  2013-03-16 16:10                                                           ` Georg Bauhaus
@ 2013-03-16 17:47                                                             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-16 17:47 UTC (permalink / raw)


On Sat, 16 Mar 2013 17:10:17 +0100, Georg Bauhaus wrote:

> On 16.03.13 14:04, Dmitry A. Kazakov wrote:

>> Why don't you simply explain why in your opinion Positive is not a type?
> 
> Whether or not Positive'Succ *is* invariant depends solely on definitions
> of Ada, not on my opinion.

You don't answer the question.

How Ada defines S'Succ is pretty clear. In question is why so and could it
be different. I already listed all variants. There are 4 of them + 1 when
the operation gets disallowed.

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



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

* Re: Is this expected behavior or not
  2013-03-16  5:52                                           ` Shark8
  2013-03-16  7:41                                             ` Dmitry A. Kazakov
@ 2013-03-16 20:45                                             ` Robert A Duff
  1 sibling, 0 replies; 242+ messages in thread
From: Robert A Duff @ 2013-03-16 20:45 UTC (permalink / raw)


Shark8 <onewingedshark@gmail.com> writes:

> On Friday, March 15, 2013 3:46:26 PM UTC-6, Robert A Duff wrote:
>> Many languages allow the type of an object to be deduced from
>> its initial value.  I believe C++ recently added that feature,
>> using the "auto" keyword (which it inherited from C, and meant
>> something completely different -- and completely useless).
>> Ada allows that in a small way -- named numbers.
>
> This isn't _quite_ the same, it's declaring an object to be of the
> same type as some other (and already known) object.

Right, I didn't mean to imply it's the same.  It's related.

>> I suspect the reason was that the designers of Ada 83 thought that
>> types of things ought to be explicit.  Except for named numbers --
>> consistency wasn't their strong suit.
>
> I thought that named numbers were of the Universal_Integer (if
> integral) or Universal_Float_and_Fixed if not... of course that could
> just be an incorrect notion I've developed.

That's correct.  My point was that named numbers are an example
where the type comes from the initial value.  If you say
"X : constant := Integer'Last;", X is of type universal_integer because
the initial value is of some integer type -- the type of X is deduced
from the type of its initial value.

- Bob



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

* Re: Is this expected behavior or not
  2013-03-16  9:29                                           ` Georg Bauhaus
@ 2013-03-16 20:49                                             ` Robert A Duff
  0 siblings, 0 replies; 242+ messages in thread
From: Robert A Duff @ 2013-03-16 20:49 UTC (permalink / raw)


Georg Bauhaus <rm.dash-bauhaus@futureapps.de> writes:

> On 15.03.13 22:46, Robert A Duff wrote:
>> That works in C because all sizes
>> are known at compile time.
>
> That's true in C89, but C99 makes sizeof an execution
> time operator for variable length arrays.

Ah, yes.  Thanks for the reminder.

>...The operand
> is then evaluated.

Right.  It seems confusing to me that the operand of sizeof is
evaluated in some cases but not others.  In Ada, the prefix of
'Size is always evaluated.

My suggestion that the prefix of 'Type could be unevaluated (always)
could work for the same reason sizeof can work like it does in C89.

- Bob



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

* Re: Is this expected behavior or not
  2013-03-16 17:36                                                 ` Dmitry A. Kazakov
@ 2013-03-16 21:51                                                   ` Shark8
  2013-03-17  9:36                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-16 21:51 UTC (permalink / raw)
  Cc: mailbox

On Saturday, March 16, 2013 11:36:57 AM UTC-6, Dmitry A. Kazakov wrote:
> On Sat, 16 Mar 2013 09:55:53 -0700 (PDT), Shark8 wrote:
> 
> > On Saturday, March 16, 2013 1:41:27 AM UTC-6, Dmitry A. Kazakov wrote:
> >> 
> >> Thus either subtypes will have same representation or you
> >> won't have a class.
> > 
> 
> > I'm thinking of it more in the terms of generic operations: independent of
> > representation.
> 
> Generics are useless for strings [and almost anything else]. 

I would disagree with that -- generics are quite useful; in the year that I was professionally programming PHP I found myself *constantly* wishing for generics (and packages, and [to a lesser extent] real records).

I think it's rather a shame that the compile-time computation aspect of generics is not emphasized a bit more -- I've got an idea for exploiting this property for planetary-orbit simulation. -- but then there are a *LOT* of things in Ada that don't get enough emphasis. (A language-level time type [& duration] is such that it obliterates an entire 'section' of Jon Skeet's talk http://vimeo.com/7403673 on common programming errors/difficulties.)

> Without class-wide objects you need a set of instances for each combination of
> encoding/character/index. No better than present mess.

I think it's not impossible to unify at least some of that -- Index, for example, is always Positive. -- I don't disagree that stings are a difficult subject, but that doesn't mean that there aren't some elegant solutions that might be applied to the problem. {Encoding might not be that difficult, we already have the character-map construct, we might be able to have an "encoding-map" which would allow us to translate freely between different encodings.}


>  >> Another problem is that string types must have more 
> >> than one interface to deal with UTF-8 etc. An UTF-8 string is *both* an
> >> array of Wide_Wide_Character (= Unicode code points) and an array or
> >> sequence of Character (octets).

That might be less of a problem than you might think; the 'Read and 'Write should handle the Octet-view while the type as-defined handles the Array-of-[[Wide_]Wide_]Character view.

> > Ah, things get tricky here; Unicode is kind of a bear when you consider
> > 'characters' because its codepoints aren't necessarily characters.
> 
> Yes, code points are glyphs.

Not all -- Unicode, bing backward-compatible w/ ASCII must have control-characters, which contradict that statement. But even disregarding those, there are characters such as the "zero-width non-joiner". (see  http://msmvps.com/blogs/jon_skeet/archive/2009/11/02/omg-ponies-aka-humanity-epic-fail.aspx )

> > An
> > example would be the so-called "combining characters" which you can use
> > for things like accents or ZALGO-text. (See these, respectively:
> 
> > http://en.wikipedia.org/wiki/Combining_character and, http://eeemo.net/ )
> 
> It is important for rendering only, if anybody uses it.

Nope, see above for the zero-width non-joiner.

> > It would be a big mistake to assume character = code-point when dealing
> > with Unicode.
> [...]
> 
> Rules according to which two texts are considered equivalent can be
> infinitely complex. You cannot do that on the basis of per character
> comparison. Character = glyph = code point is good enough for most
> applications.

> > I guess what I'm trying to say is that if we did it right, we could
> > modify/expand the type-system so that something like UNIVERSAL_INTEGER
> > could be made/explicitly-specified.
> 
> Arrays must have interfaces. Array interface should vary along the index
> and element "axes" forming a class. Any type should have a class. It should
> be possible to drop implementation upon inheritance composing operations
> with type conversion. That is basically all. It would be fully backward
> compatible. Actual problems lie elsewhere [MD, parallel type hierarchies].

Parallel type hierarchies are probably the way address GUI -- you could have one for the graphical side and one for the data-side -- but I'm fairly impressed with the way Delphi handled it with the VCL. {Yes there are some warts, but that system works very well in-practice; indeed the C#/.NET components/events is a near-direct plagiarism [though w/ worse event-names, IMO]}.

> > In any case; I think it worth considering not just outward/downward
> > expansion of the language, but inward/upward [unification] as well.
> 
> Welcome in the club. But in order to be able to weight proposals you need a
> more or less formal framework to describe language type system. Already
> this little faces a fierce opposition. So don't expect much.

This is likely to be true -- but I think the reward for doing so would outweigh the costs. {Especially if we could unify strings s.t. the [[Wide_]Wide_]Character packages are merely 'instantiations' of an "abstract string."}



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

* Re: Is this expected behavior or not
  2013-03-16 21:51                                                   ` Shark8
@ 2013-03-17  9:36                                                     ` Dmitry A. Kazakov
  2013-03-18 23:13                                                       ` Randy Brukardt
  2013-03-19  0:38                                                       ` Shark8
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-17  9:36 UTC (permalink / raw)


On Sat, 16 Mar 2013 14:51:58 -0700 (PDT), Shark8 wrote:

> I think it's rather a shame that the compile-time computation aspect of
> generics is not emphasized a bit more

You need no generics in order to compute something statically. Yes Ada
could be much better with an ability to declare a function static or
conditionally static.
 
>> Without class-wide objects you need a set of instances for each combination of
>> encoding/character/index. No better than present mess.
> 
> I think it's not impossible to unify at least some of that -- Index, for
> example, is always Positive. -- I don't disagree that stings are a
> difficult subject, but that doesn't mean that there aren't some elegant
> solutions that might be applied to the problem.

I commented on a generic solution which would necessarily preserve the
status quo that string types are unrelated. This is the key point. In order
to reduce complexity we need operations like Put_Line become either
class-wide or primitive [both operate on whole class].

>>  >> Another problem is that string types must have more 
>>>> than one interface to deal with UTF-8 etc. An UTF-8 string is *both* an
>>>> array of Wide_Wide_Character (= Unicode code points) and an array or
>>>> sequence of Character (octets).
> 
> That might be less of a problem than you might think; the 'Read and 'Write
> should handle the Octet-view while the type as-defined handles the
> Array-of-[[Wide_]Wide_]Character view.

That would make string tagged, which in turn would imply certain
representation [embedded tag] and forced by-reference semantics. The
consequences are far reaching, e.g. you would have to drop slices etc.

My wish is to allow T'Class constructed for an untagged type by adding a
tag. E.g. T and T'Class would have different representations.

This is again a key issue. Ada often conflates interface and
representation/implementation. This must be fixed. But I am not even
allowed to name

   subtype Positive is Integer range 1..Integer'Last;

a type. What would happed if I asked to be able to provide an alternative
representation for Positive? To disallow unary minus?

>>> In any case; I think it worth considering not just outward/downward
>>> expansion of the language, but inward/upward [unification] as well.
>> 
>> Welcome in the club. But in order to be able to weight proposals you need a
>> more or less formal framework to describe language type system. Already
>> this little faces a fierce opposition. So don't expect much.
> 
> This is likely to be true -- but I think the reward for doing so would
> outweigh the costs. {Especially if we could unify strings s.t. the
> [[Wide_]Wide_]Character packages are merely 'instantiations' of an
> "abstract string."}

It is not only strings. There are other types which are presently unrelated
though share various interfaces [Ordered, Copyable, Comparable, Additive,
Multiplicative, Indexed, Record etc]. The language does not allow to
specify interfaces and have class-wide instances of those.

I presume that back in 90's there was too much opposition to overhaul the
type system. Tagged types were added to the existing types, while one
should have made classes and interfaces fundamental to all types. We got an
outbuilding instead of new fundament. [We must be happy that Taft managed
to pressure for at least this change.]

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



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

* Re: Is this expected behavior or not
  2013-03-16  7:51                                                 ` Dmitry A. Kazakov
  2013-03-16  9:30                                                   ` Georg Bauhaus
@ 2013-03-18 22:36                                                   ` Randy Brukardt
  2013-03-19 10:14                                                     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-18 22:36 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:hiybjkhz3p5d.1x6dxfr1ptgcg.dlg@40tude.net...
> On Fri, 15 Mar 2013 16:17:11 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:ewe0v3ck1xdo$.e8rtuof27ke6$.dlg@40tude.net...
>>> On Thu, 14 Mar 2013 17:12:28 -0500, Randy Brukardt wrote:
>>>
>>>> There are some differences in *dynamic* behavior, but that has nothing 
>>>> to do
>>>> with the available values and operations. (The text you quoted from the 
>>>> RM
>>>> about values "belonging" to a subtype is defining dynamic behavior.) I
>>>> recall some Dmitry guy telling us that dynamic behavior is different 
>>>> from
>>>> static behavior, and even claiming that dynamic behavior cannot 
>>>> constitute a
>>>> contract. So it if is not a *contract*, how come it matters for a 
>>>> *type*
>>>> (which is an integral part of describing a contract)?
>>>
>>> I don't understand the point you are making. You cannot derive contract
>>> from behavior, simply because it is converse: contract is imposed to
>>> restrain possible behaviors.
>>>
>>> You might claim that implied contracts of Integer and Positive are 
>>> exactly
>>> same. I doubt that many would agree with that.
>>
>> I certainly wouldn't, because *I* consider the dynamic behavior to be 
>> part
>> of the contract. But, clearly, you don't (and you've indicated that above
>> again. So yes, given your world view, the contracts of Integer and 
>> Positive
>> are exactly the same. That's clear, because they're interchangable in 
>> terms
>> of legality and resolution (anything having to do with compile-time
>> checking). The quote above says that you disagree with yourself. :-)
>
> That would be a consequence of considering them same type. I already said,
> that this a path towards weak typing.
>
> But I don't see where I disagree with myself. Contract /= type. You can
> have same contract and different types. What about:
>
>   type Same is new Integer;

This definitely has a different contract, as it is not compatible with 
Integer's contract. Yes, it has the same set of values and operations with 
the same name, profile, and bodies, but it's still a different contract 
because the types involved are an intergral part of the contract.

> You also can have different contracts put on the same type in different
> contexts. You can have contracts on something that does not involve types
> at all. Anyway, I fail to see how contracts are relevant here.

Because types are an important part of a contract (that is, in Ada terms, 
the profile). Two operations with different profiles are different, even if 
everything else is the same (the implementation, names of things, etc.)

...
> I don't see why. How *any* contract could make something like Positive a
> non-type? There is not many possibilities:
>
> A. Positive is not a type. This is what Georg says. I have no idea what
> this is supposed to mean. That 123 is not Positive, or that "+" is not
> applied to positives? He escapes into some kind of vague philosophy each
> time I ask.

I agree with Georg; Positive is not a type; it *has* a type. Neither is 
Integer a type; it *has* a type. (All types in Ada are anonymous.) As such, 
the "+" that applied to Positive is the same one that's applied to Integer. 
That's *not* the case for a type like the one associated with Same, as you 
declared it above.

> B. Positive is a type. The type is Integer. So Positive = Integer. This is
> evidently wrong because there exist programs which semantics sufficiently
> change when 'Integer' is replaced by 'Positive'. If the language treats
> them same, worse to the language. Luckily Ada checks if Positive is indeed
> positive (well, not always, but almost).

This is also true, except for the first sentence. But you're confusing the 
issue by talking about "semantics". Types are only about static semantics 
(that is, compile-time behavior). Run-time semantics aren't involved. It's 
the same as for profiles, operations, and the like.

In this sense, a type is part of your model for contracts, where there is no 
run-time component.

Run-time semantics get added on top of that, but that has no effect on the 
legality of a program, so it is completely orthogonal to the type/profile.

> C. not (A or B) = my point.

Actually, both A and B are true, claiming their exclusive doesn't make any 
sense. Or maybe it's better to call them irrelevant, as the relationship 
"is" doesn't apply to "Positive" and "type" in Ada (or any named entity, for 
that matter). It would be like saying:

A. Dump truck is not an engine.
B. Dump truck is an engine.
C. not (A or B).

C is the only statement that makes sense here, as a dump truck "has" an 
engine, but it surely is not an engine. (It has many other parts as well, 
and the same is true for Positive.)

                                 Randy.






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

* Re: Is this expected behavior or not
  2013-03-16  7:56                                         ` Dmitry A. Kazakov
@ 2013-03-18 22:52                                           ` Randy Brukardt
  2013-03-19 10:32                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-18 22:52 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:a9ivriefwvbm.1mwi80nz4jz6h$.dlg@40tude.net...
> On Fri, 15 Mar 2013 16:43:47 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1xsmzl7alqflb$.oz1qkrleisa7$.dlg@40tude.net...
>>> On Thu, 14 Mar 2013 16:51:11 -0500, Randy Brukardt wrote:
>>>
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>>> news:13y3efy877tjl$.5yuu230sknnq$.dlg@40tude.net...
...
>>>>> How do you describe tagged types in Ada 83 terms?
>>>>
>>>> Why would I want to?
>>>
>>> You insisted on that claiming that Ada can be only discussed in 
>>> Ada-terms.
>>
>> You didn't answer the question. Why would you want to describe something
>> from a recent version of the language in terms of an obsolete one?
>
> To illustrate the point that one cannot extend/modify the language
> discussing it in its terms, like baron Munchausen pulling yourself out of 
> a
> swamp by your hair.

We're not talking about extending or modifying the language, so that would 
not be relevant.

> How would you tell yourself from year 1992 about Ada 95? The other you
> would not listen to you.

Well, in 1992, we were already working on implementation Ada 9x (which 
became Ada 95), as we were part of one of the user/implementer teams. So it 
wouldn't be hard at all to do. :-) And Ada 9x was described in terms of 
extending existing Ada concepts, so it wasn't that hard to understand at 
all.


...
>>> Ada's subtype as defined by RM is a fact to explain (and to predict
>>> consequences of the choices made). The theory does it quite well. The 
>>> rant
>>> about how Ada's RM names its subtypes is absolutely irrelevant.
>>
>> But no one cares, because such matching has no relevance to anything: 
>> it's
>> not going to change the design of Ada (compatibility concerns would 
>> prevent
>> that in any case)
>
> There is no compatibility concerns. Robert said in this thread that
> Prime'Range, Prime'First, Prime'Last are all illegal. So it is already
> incompatible, if under compatibility you understand that a subtype must
> inherit everything.

Huh? In this content, "Compatibility" means new versions of Ada should not 
break existing Ada code. For the definition of 'Succ, for example, we cannot 
change it without potentially breaking existing code, so it is unlikely that 
we would make such a change.

>> and nothing about it would help you be a better Ada
>> programmer (especially as the terminology clash makes it close to 
>> impossible
>> to think about one and make sense of the other).
>
> On the contrary, understanding that a subtype is a type with values and
> operation helps a lot. Especially when it comes to aberrations like with
> Prime'Succ. It is an operation of Prime and the programmer should know 
> that
> in Ada he has no influence on its implementation which is always inherited
> from the base type. If that does not correspond his intent he must change
> the design and use other means, e.g. tagged types or unrelated types
> (derive Prime privately).

You seem to get the right conclusion from the wrong premise. If you 
understand that Positive is not a type, but rather *has* a type, and 
operations are chosen based on the type that Positive has (not by the 
subtype), then the behavior of  'Succ makes perfect sense, because its the 
same behavior that you get for "+" and "*" and all of the other predefined 
operations.

Prime'Succ is thus an operation of Integer'Base (as subtypes like Prime 
don't have operations), and clearly how it behaves is based on that.

And yes, if you want some other behavior, then you have to write it 
yourself -- nothing new about that.

                                        Randy.





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

* Re: Is this expected behavior or not
  2013-03-17  9:36                                                     ` Dmitry A. Kazakov
@ 2013-03-18 23:13                                                       ` Randy Brukardt
  2013-03-19  9:12                                                         ` Dmitry A. Kazakov
  2013-03-19  0:38                                                       ` Shark8
  1 sibling, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-18 23:13 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1hvv2kd9smnfx.6spgz9thd1mh$.dlg@40tude.net...
...
>> That might be less of a problem than you might think; the 'Read and 
>> 'Write
>> should handle the Octet-view while the type as-defined handles the
>> Array-of-[[Wide_]Wide_]Character view.
>
>That would make string tagged, which in turn would imply certain
>representation [embedded tag] and forced by-reference semantics. The
>consequences are far reaching, e.g. you would have to drop slices etc.

For string, requiring by-reference would have little practical effect, as 
almost all compilers pass strings by-reference anyway. There is no OOP-way 
to make slicing work, since slices are by definition references (in C-terms, 
they're an l-value), and since the representations have to vary, that isn't 
going to be possible.

My rough proposed Root_String_Type would be an abstract tagged type, but it 
wouldn't provide slices directly (it would provide functions for that 
purpose). But that's OK, because such a construct would have to be alongside 
the existing string types; we can't replace or change them in any 
significant way and I think that means we'll have to start over.

...
> This is again a key issue. Ada often conflates interface and
> representation/implementation. This must be fixed. But I am not even
> allowed to name
>
>   subtype Positive is Integer range 1..Integer'Last;
>
> a type. What would happed if I asked to be able to provide an alternative
> representation for Positive? To disallow unary minus?

That's easy: nothing would happen. Compatibility with existing code almost 
always has priority. If you can describe the changes in terms of the 
existing semantics, then you might have a chance, but if you invent your own 
terminology and propose to throw out the existing rules, no one is going to 
pay much attention. Even if you are right (and you may very well be right), 
it is just too likely to introduce intolerable incompatibilities.

...
> I presume that back in 90's there was too much opposition to overhaul the
> type system. Tagged types were added to the existing types, while one
> should have made classes and interfaces fundamental to all types. We got 
> an
> outbuilding instead of new fundament. [We must be happy that Taft managed
> to pressure for at least this change.]

You do know that the original Ada 9x design was much like you are 
describing, with 'Class for all types? 'Class for untagged types eventually 
got dropped because of various semantics issues (mainly, they just worked 
differently than the tagged version, and that was thought to be 
confusing) -- and when people thought that Ada 9x was just too large and 
stuff had to go, that was one of the first.

Of course, for composite types, almost everything should be tagged and 
controlled (there would have to be a critical memory usage reason to avoid 
that), and in that case everything works sanely. (Even indexing, given the 
new Ada 2012 features). So we're mostly talking about scalar type 'Class (we 
don't need any more anonymous access types of any kind, and they're 
essentially structural equivalence as it is, so 'Class would buy very little 
there).

I think the more interesting thing is that we've never brought it back. It 
seems that we haven't seen any truly compelling uses for the idea, because 
if we had, I'm sure it would have come back in Ada 2005 or Ada 2012.

                                              Randy.





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

* Re: Is this expected behavior or not
  2013-03-17  9:36                                                     ` Dmitry A. Kazakov
  2013-03-18 23:13                                                       ` Randy Brukardt
@ 2013-03-19  0:38                                                       ` Shark8
  2013-03-19  8:53                                                         ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-19  0:38 UTC (permalink / raw)
  Cc: mailbox

On Sunday, March 17, 2013 3:36:19 AM UTC-6, Dmitry A. Kazakov wrote:
> On Sat, 16 Mar 2013 14:51:58 -0700 (PDT), Shark8 wrote:
> 
> > I think it's rather a shame that the compile-time computation aspect of
> > generics is not emphasized a bit more
> 
> You need no generics in order to compute something statically. Yes Ada
> could be much better with an ability to declare a function static or
> conditionally static.

You misunderstand me; I wasn't saying that generics were required for compile-time computation, but that their use in compile-time computation is an interesting topic. (For example you could make a solar-system simulator by making 'orbit' a generic with the parameters cooresponding to Kepler's laws of motion.)



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

* Re: Is this expected behavior or not
  2013-03-19  0:38                                                       ` Shark8
@ 2013-03-19  8:53                                                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-19  8:53 UTC (permalink / raw)


On Mon, 18 Mar 2013 17:38:34 -0700 (PDT), Shark8 wrote:

> On Sunday, March 17, 2013 3:36:19 AM UTC-6, Dmitry A. Kazakov wrote:
>> On Sat, 16 Mar 2013 14:51:58 -0700 (PDT), Shark8 wrote:
>> 
>>> I think it's rather a shame that the compile-time computation aspect of
>>> generics is not emphasized a bit more
>> 
>> You need no generics in order to compute something statically. Yes Ada
>> could be much better with an ability to declare a function static or
>> conditionally static.
> 
> You misunderstand me; I wasn't saying that generics were required for
> compile-time computation, but that their use in compile-time computation
> is an interesting topic.

Surely it is, especially for static checks/constraints defined by the user
as it would be necessary for dimensioned arithmetic, matrix calculus etc.

> (For example you could make a solar-system
> simulator by making 'orbit' a generic with the parameters cooresponding to
> Kepler's laws of motion.)

Again, you don't need generics that. If you want "laws" be parameter bundle
them into an interface. Generics/templates/preprocessor have no other
purpose than to cover work around deficiencies of the language type system,
premature optimization, lack of abstraction means.

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



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

* Re: Is this expected behavior or not
  2013-03-18 23:13                                                       ` Randy Brukardt
@ 2013-03-19  9:12                                                         ` Dmitry A. Kazakov
  2013-03-19 21:19                                                           ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-19  9:12 UTC (permalink / raw)


On Mon, 18 Mar 2013 18:13:39 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1hvv2kd9smnfx.6spgz9thd1mh$.dlg@40tude.net...
> ...
>>> That might be less of a problem than you might think; the 'Read and 'Write
>>> should handle the Octet-view while the type as-defined handles the
>>> Array-of-[[Wide_]Wide_]Character view.
>>
>>That would make string tagged, which in turn would imply certain
>>representation [embedded tag] and forced by-reference semantics. The
>>consequences are far reaching, e.g. you would have to drop slices etc.
> 
> For string, requiring by-reference would have little practical effect, as 
> almost all compilers pass strings by-reference anyway. There is no OOP-way 
> to make slicing work, since slices are by definition references (in C-terms, 
> they're an l-value), and since the representations have to vary, that isn't 
> going to be possible.

It is well possible. Consider tag a constraint as array bounds are. Allow
constraints (=discriminants) passed independently as compilers already do
for array bounds. This gives you array interfaces while keeping arrays as
they are, plain arrays.

> My rough proposed Root_String_Type would be an abstract tagged type,

I definitely don't want strings tagged.

> but it 
> wouldn't provide slices directly (it would provide functions for that 
> purpose). But that's OK, because such a construct would have to be alongside 
> the existing string types; we can't replace or change them in any 
> significant way and I think that means we'll have to start over.

But we can. The point is that the existing type system of Ada is fully
compatible with the system I am talking about. There is no compatibility
issues.

> So we're mostly talking about scalar type 'Class (we 
> don't need any more anonymous access types of any kind, and they're 
> essentially structural equivalence as it is, so 'Class would buy very little 
> there).

No, this is a huge difference. Especially for scalar types we need clear
interfaces because otherwise programs get infested by a combinatorial
explosion of generic instances.

Presently, I am unable to compile my project under any 32-bit system
because GNAT compiler needs 3GB an more to instantiate all generics, apart
from that this takes 3-4 hours on an i7, and the project has hundreds of
meaningless packages which only purpose is to instantiate.
 
-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Is this expected behavior or not
  2013-03-18 22:36                                                   ` Randy Brukardt
@ 2013-03-19 10:14                                                     ` Dmitry A. Kazakov
  2013-03-19 14:23                                                       ` Georg Bauhaus
  2013-03-19 21:37                                                       ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-19 10:14 UTC (permalink / raw)


On Mon, 18 Mar 2013 17:36:31 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:hiybjkhz3p5d.1x6dxfr1ptgcg.dlg@40tude.net...

>> But I don't see where I disagree with myself. Contract /= type. You can
>> have same contract and different types. What about:
>>
>>   type Same is new Integer;
> 
> This definitely has a different contract, as it is not compatible with 
> Integer's contract. Yes, it has the same set of values and operations with 
> the same name, profile, and bodies, but it's still a different contract 
> because the types involved are an intergral part of the contract.

See, you just defined a contract in terms of types while using contracts to
define type as same/different/non-existent. You cannot have it in both
ways.

>> You also can have different contracts put on the same type in different
>> contexts. You can have contracts on something that does not involve types
>> at all. Anyway, I fail to see how contracts are relevant here.
> 
> Because types are an important part of a contract (that is, in Ada terms, 
> the profile).

*if* you want to contract a type, *then* that cannot be a part of.

In any case, contract is much less a language term than type. It is more
about design and the problem space. It may apply to a type when the type is
used to represent some domain entity but it cannot define what types are. A
type is values+operations.

> Two operations with different profiles are different, even if 
> everything else is the same (the implementation, names of things, etc.)

Ada has *nominal* equivalence of operations. Two operations are different
just because they are declared in different places. It is not because of
their profiles. On top of that there are rules about overloading/overriding
where profiles get involved, but that is not like C where you can repeat
declarations.

>> I don't see why. How *any* contract could make something like Positive a
>> non-type? There is not many possibilities:
>>
>> A. Positive is not a type. This is what Georg says. I have no idea what
>> this is supposed to mean. That 123 is not Positive, or that "+" is not
>> applied to positives? He escapes into some kind of vague philosophy each
>> time I ask.
> 
> I agree with Georg; Positive is not a type; it *has* a type. Neither is 
> Integer a type; it *has* a type.

Since there is an equivalence between Positive and the type is "has,"
Positive as a name unambiguously refers to that type, i.e. "Positive" is
the name of the type. Unless you have other legal name for it. But you
don't in Ada. You have absolutely no language means whatsoever to
distinguish Positive and the type of. So, what merits has this distinction
if it cannot be observed?

> (All types in Ada are anonymous.)

Great, then let them be, where there belong to, in the celestial spheres,
and let us call type something that indeed exists in the language and has a
name.

> Types are only about static semantics 
> (that is, compile-time behavior). Run-time semantics aren't involved.

Run-time semantics is what makes program working or not working. Types are
all about run-time semantics nothing else counts.

Type checks is a way to prove something about [run-time] semantics at
compile time. Types neither ensure nor required for a program to behave
correctly. They are a tool to ease reaching that goal.

> Run-time semantics get added on top of that, but that has no effect on the 
> legality of a program, so it is completely orthogonal to the type/profile.

Legality is irrelevant as we consider only legal Ada programs. There exist
legal Ada programs which change their run-time behavior when 'Positive' is
replaced by 'Integer' and reverse.
 
-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Is this expected behavior or not
  2013-03-18 22:52                                           ` Randy Brukardt
@ 2013-03-19 10:32                                             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-19 10:32 UTC (permalink / raw)


On Mon, 18 Mar 2013 17:52:03 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:a9ivriefwvbm.1mwi80nz4jz6h$.dlg@40tude.net...
>> On Fri, 15 Mar 2013 16:43:47 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:1xsmzl7alqflb$.oz1qkrleisa7$.dlg@40tude.net...
>>>> On Thu, 14 Mar 2013 16:51:11 -0500, Randy Brukardt wrote:
>>>>
>>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>>>> news:13y3efy877tjl$.5yuu230sknnq$.dlg@40tude.net...
> ...
>>>>>> How do you describe tagged types in Ada 83 terms?
>>>>>
>>>>> Why would I want to?
>>>>
>>>> You insisted on that claiming that Ada can be only discussed in 
>>>> Ada-terms.
>>>
>>> You didn't answer the question. Why would you want to describe something
>>> from a recent version of the language in terms of an obsolete one?
>>
>> To illustrate the point that one cannot extend/modify the language
>> discussing it in its terms, like baron Munchausen pulling yourself out of 
>> a swamp by your hair.
> 
> We're not talking about extending or modifying the language, so that would 
> not be relevant.

It is the same context though.

>>>> Ada's subtype as defined by RM is a fact to explain (and to predict
>>>> consequences of the choices made). The theory does it quite well. The rant
>>>> about how Ada's RM names its subtypes is absolutely irrelevant.
>>>
>>> But no one cares, because such matching has no relevance to anything: it's
>>> not going to change the design of Ada (compatibility concerns would prevent
>>> that in any case)
>>
>> There is no compatibility concerns. Robert said in this thread that
>> Prime'Range, Prime'First, Prime'Last are all illegal. So it is already
>> incompatible, if under compatibility you understand that a subtype must
>> inherit everything.
> 
> Huh? In this content, "Compatibility" means new versions of Ada should not 
> break existing Ada code. For the definition of 'Succ, for example, we cannot 
> change it without potentially breaking existing code, so it is unlikely that 
> we would make such a change.

Of course you can do it without breaking anything. Making an operation
primitive and allowing it to be overridden, can break nothing.

But actually S'Succ (X) shall go straight to the section J. We should
introduce X'Succ, a primitive operation of the interface Ordered and forget
about the mess. Instead of deriving Prime from Integer and inheriting what
should not be there, you would do from Copyable, add user-defined literals
(=inherit some integer literals, which are functions, of course), and
privately implement it as Integer.

>>> and nothing about it would help you be a better Ada
>>> programmer (especially as the terminology clash makes it close to 
>>> impossible to think about one and make sense of the other).
>>
>> On the contrary, understanding that a subtype is a type with values and
>> operation helps a lot. Especially when it comes to aberrations like with
>> Prime'Succ. It is an operation of Prime and the programmer should know that
>> in Ada he has no influence on its implementation which is always inherited
>> from the base type. If that does not correspond his intent he must change
>> the design and use other means, e.g. tagged types or unrelated types
>> (derive Prime privately).
> 
> You seem to get the right conclusion from the wrong premise.

So, the theory works.

> If you 
> understand that Positive is not a type, but rather *has* a type, and 
> operations are chosen based on the type that Positive has (not by the 
> subtype), then the behavior of  'Succ makes perfect sense, because its the 
> same behavior that you get for "+" and "*" and all of the other predefined 
> operations.

No, it does not make sense, because the semantics of Prime is not defined
by RM, it is in the realm of mathematics.

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



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

* Re: Is this expected behavior or not
  2013-03-19 10:14                                                     ` Dmitry A. Kazakov
@ 2013-03-19 14:23                                                       ` Georg Bauhaus
  2013-03-19 15:13                                                         ` Dmitry A. Kazakov
  2013-03-19 21:37                                                       ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-19 14:23 UTC (permalink / raw)


On 19.03.13 11:14, Dmitry A. Kazakov wrote:
> "Positive" is the name of the type.

How can something have a name if it is known to be anonymous?



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

* Re: Is this expected behavior or not
  2013-03-19 14:23                                                       ` Georg Bauhaus
@ 2013-03-19 15:13                                                         ` Dmitry A. Kazakov
  2013-03-19 16:52                                                           ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-19 15:13 UTC (permalink / raw)


On Tue, 19 Mar 2013 15:23:15 +0100, Georg Bauhaus wrote:

> On 19.03.13 11:14, Dmitry A. Kazakov wrote:
>> "Positive" is the name of the type.
> 
> How can something have a name if it is known to be anonymous?

   http://en.wikipedia.org/wiki/Name

The first two sentences.

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



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

* Re: Is this expected behavior or not
  2013-03-19 15:13                                                         ` Dmitry A. Kazakov
@ 2013-03-19 16:52                                                           ` Georg Bauhaus
  2013-03-19 17:31                                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-19 16:52 UTC (permalink / raw)


On 19.03.13 16:13, Dmitry A. Kazakov wrote:
> On Tue, 19 Mar 2013 15:23:15 +0100, Georg Bauhaus wrote:
> 
>> On 19.03.13 11:14, Dmitry A. Kazakov wrote:
>>> "Positive" is the name of the type.
>>
>> How can something have a name if it is known to be anonymous?
> 
>    http://en.wikipedia.org/wiki/Name
> 
> The first two sentences.

These names apply to things that are eligible for naming.
An Ada type, by definition, is not eligible for naming
(like you have said). That's the rule of law.

It was a joke, anyway. I'm still waiting for the set of
formalized definitions that rewrite LRM 3, since they need
to put down words that redefine "type" and "subtype" from
the ground up (even when that's "just ..."). Until then,
everything conflates matters, I think.




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

* Re: Is this expected behavior or not
  2013-03-19 16:52                                                           ` Georg Bauhaus
@ 2013-03-19 17:31                                                             ` Dmitry A. Kazakov
  2013-03-19 20:07                                                               ` J-P. Rosen
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-19 17:31 UTC (permalink / raw)


On Tue, 19 Mar 2013 17:52:13 +0100, Georg Bauhaus wrote:

> I'm still waiting for the set of
> formalized definitions that rewrite LRM 3, since they need
> to put down words that redefine "type" and "subtype" from
> the ground up (even when that's "just ...").

Positive is the name of an abstract data type with values from 1 to
Integer'Last and operations inherited from the type, which name is Integer.

Type is a tuple: set of values x set of operations [with at least an
argument or result of the type].

Subtype is a type that inherits some operations (interface) of another
type, called "parent type," "base type," "ancestor type" or "supertype."

Subtyping relation is transitive and reflexive.

Class is the transitive closure of.

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



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

* Re: Is this expected behavior or not
  2013-03-19 17:31                                                             ` Dmitry A. Kazakov
@ 2013-03-19 20:07                                                               ` J-P. Rosen
  2013-03-19 20:45                                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-03-19 20:07 UTC (permalink / raw)


Le 19/03/2013 18:31, Dmitry A. Kazakov a �crit :
> Subtype is a type that inherits some operations (interface) of another
> type, called "parent type," "base type," "ancestor type" or "supertype."

This may be the source of the confusion. What you describe is called
"subtype" in other languages, but this is called "derived type" in Ada.
An Ada subtype is a completely different beast, that does not correspond
to this definition.

And please, bear in mind that other languages do not have anything
similar to Ada subtypes, therefore you cannot compare Ada subtypes to
features of other languages.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-19 20:07                                                               ` J-P. Rosen
@ 2013-03-19 20:45                                                                 ` Dmitry A. Kazakov
  2013-03-19 21:59                                                                   ` J-P. Rosen
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-19 20:45 UTC (permalink / raw)


On Tue, 19 Mar 2013 21:07:18 +0100, J-P. Rosen wrote:

> Le 19/03/2013 18:31, Dmitry A. Kazakov a �crit :
>> Subtype is a type that inherits some operations (interface) of another
>> type, called "parent type," "base type," "ancestor type" or "supertype."
> 
> This may be the source of the confusion. What you describe is called
> "subtype" in other languages, but this is called "derived type" in Ada.
> An Ada subtype is a completely different beast, that does not correspond
> to this definition.

And how is it different?

> And please, bear in mind that other languages do not have anything
> similar to Ada subtypes, therefore you cannot compare Ada subtypes to
> features of other languages.

Practically all languages have subtypes which share the representation of
the parent while adding a constraint. E.g. const T in C++ is such a
subtype.

Of course insistence on keeping the representation erodes the principle of
separation interface and implementation. Ada would be much better off if
all derived types could change the representation like arrays do when
constrained.

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



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

* Re: Is this expected behavior or not
  2013-03-19  9:12                                                         ` Dmitry A. Kazakov
@ 2013-03-19 21:19                                                           ` Randy Brukardt
  2013-03-20 11:21                                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-19 21:19 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:vo941i7imo8t$.1jjjox9r1hkqa.dlg@40tude.net...
> On Mon, 18 Mar 2013 18:13:39 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1hvv2kd9smnfx.6spgz9thd1mh$.dlg@40tude.net...
>> ...
>>>> That might be less of a problem than you might think; the 'Read and 
>>>> 'Write
>>>> should handle the Octet-view while the type as-defined handles the
>>>> Array-of-[[Wide_]Wide_]Character view.
>>>
>>>That would make string tagged, which in turn would imply certain
>>>representation [embedded tag] and forced by-reference semantics. The
>>>consequences are far reaching, e.g. you would have to drop slices etc.
>>
>> For string, requiring by-reference would have little practical effect, as
>> almost all compilers pass strings by-reference anyway. There is no 
>> OOP-way
>> to make slicing work, since slices are by definition references (in 
>> C-terms,
>> they're an l-value), and since the representations have to vary, that 
>> isn't
>> going to be possible.
>
> It is well possible. Consider tag a constraint as array bounds are. Allow
> constraints (=discriminants) passed independently as compilers already do
> for array bounds. This gives you array interfaces while keeping arrays as
> they are, plain arrays.

No, it's not possible. In order to solve the string problem, we have to 
decouple the representation and the interface. But for slices, you have to 
know the representation in order to be able to pass it meaningfully. 
Moreover, the representation is not necessarily an array (UTF-8 encoding is 
not a normal array if you are using the character interface). So 
by-reference passing of part of something that is not necessarily a 
contiguous array is not possible. (In addition, such an interface ought to 
support chunked representations and the like, and again that cannot pass 
just a part.)

>> My rough proposed Root_String_Type would be an abstract tagged type,
>
> I definitely don't want strings tagged.

Then forget it. All composite types ought to be tagged; the root of the 
existing problem is that arrays aren't tagged.

>> but it
>> wouldn't provide slices directly (it would provide functions for that
>> purpose). But that's OK, because such a construct would have to be 
>> alongside
>> the existing string types; we can't replace or change them in any
>> significant way and I think that means we'll have to start over.
>
> But we can. The point is that the existing type system of Ada is fully
> compatible with the system I am talking about. There is no compatibility
> issues.

You're dreaming - it's not possible. As soon as you change the inheritance 
rules (which you have to do), you'll break the semantics of derived types 
(they'll inherit different operations). The only alternative to that is to 
invent a totally new kind of type declaration that pretty similar to derived 
types -- and that will never fly as it would be too confusing to users.

>> So we're mostly talking about scalar type 'Class (we
>> don't need any more anonymous access types of any kind, and they're
>> essentially structural equivalence as it is, so 'Class would buy very 
>> little
>> there).
>
> No, this is a huge difference. Especially for scalar types we need clear
> interfaces because otherwise programs get infested by a combinatorial
> explosion of generic instances.

I don't follow. I said we need 'Class for scalar types (but not access 
types), and you said no, we need 'Class for scalar types. I don't think we 
need 'Class for access types, because the effect is essentially the same as 
what we already have for anonymous access types (the only real change needed 
would be to give those kinds of access types an optional name). I could 
imagine some disagreement on this latter point, but not on the first one.

> Presently, I am unable to compile my project under any 32-bit system
> because GNAT compiler needs 3GB an more to instantiate all generics, apart
> from that this takes 3-4 hours on an i7, and the project has hundreds of
> meaningless packages which only purpose is to instantiate.

For someone that hates generics, why would you have so many? My programs are 
almost generic-free, most of the ones I have are one-offs like iterators and 
binary data readers (like Sequential_IO). The few times I've goine further, 
I've regretted it.

Maybe you're trying too hard to be Object-Oriented; I find that is almost 
never worth the effort -- just build a good ADT and make it tagged and 
controlled so that the next person can extend it if they have to. (But 
hopefully they won't have to.)

                                               Randy. 





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

* Re: Is this expected behavior or not
  2013-03-19 10:14                                                     ` Dmitry A. Kazakov
  2013-03-19 14:23                                                       ` Georg Bauhaus
@ 2013-03-19 21:37                                                       ` Randy Brukardt
  2013-03-20  8:48                                                         ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-19 21:37 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:vawvqtrqgamw$.1gsl8m14dvk4i.dlg@40tude.net...
> On Mon, 18 Mar 2013 17:36:31 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:hiybjkhz3p5d.1x6dxfr1ptgcg.dlg@40tude.net...
>
>>> But I don't see where I disagree with myself. Contract /= type. You can
>>> have same contract and different types. What about:
>>>
>>>   type Same is new Integer;
>>
>> This definitely has a different contract, as it is not compatible with
>> Integer's contract. Yes, it has the same set of values and operations 
>> with
>> the same name, profile, and bodies, but it's still a different contract
>> because the types involved are an intergral part of the contract.
>
> See, you just defined a contract in terms of types while using contracts 
> to
> define type as same/different/non-existent. You cannot have it in both
> ways.

If you can't handle recursive definitions, you'll never get very far in 
programming language design. The only requirement is that each step gets 
simpler, which certainly is the case here.

>>> You also can have different contracts put on the same type in different
>>> contexts. You can have contracts on something that does not involve 
>>> types
>>> at all. Anyway, I fail to see how contracts are relevant here.
>>
>> Because types are an important part of a contract (that is, in Ada terms,
>> the profile).
>
> *if* you want to contract a type, *then* that cannot be a part of.

A type *has* a contract. A contract is made up (in part) of types. No 
problem.

...

...
>> I agree with Georg; Positive is not a type; it *has* a type. Neither is
>> Integer a type; it *has* a type.
>
> Since there is an equivalence between Positive and the type is "has,"

No, there is not any equivalence. "Type" is just one property of "Positive", 
and it might have the same value as that of some other subtype (like 
"Natural").

> Positive as a name unambiguously refers to that type, i.e. "Positive" is
> the name of the type. Unless you have other legal name for it. But you
> don't in Ada. You have absolutely no language means whatsoever to
> distinguish Positive and the type of. So, what merits has this distinction
> if it cannot be observed?

"The type of Positive" unambigiously identifies that property for 
"Positive". There is not "name" (that is, identifier) associated with that 
property.

>> (All types in Ada are anonymous.)
>
> Great, then let them be, where there belong to, in the celestial spheres,
> and let us call type something that indeed exists in the language and has 
> a
> name.

Well, if you insist on naming the unnameable, you'll never reach any useful 
understanding. If you absolutely have to have a name, call it "the type of 
Positive" or "Positive'Base" (not all types have the 'Base attribute, or you 
could use that as the name).

And Positive'Base = Integer'Base = Natural'Base.

>> Types are only about static semantics
>> (that is, compile-time behavior). Run-time semantics aren't involved.
>
> Run-time semantics is what makes program working or not working. Types are
> all about run-time semantics nothing else counts.

Then we really have nothing to talk about.

> Type checks is a way to prove something about [run-time] semantics at
> compile time. Types neither ensure nor required for a program to behave
> correctly. They are a tool to ease reaching that goal.
>
>> Run-time semantics get added on top of that, but that has no effect on 
>> the
>> legality of a program, so it is completely orthogonal to the 
>> type/profile.
>
> Legality is irrelevant as we consider only legal Ada programs. There exist
> legal Ada programs which change their run-time behavior when 'Positive' is
> replaced by 'Integer' and reverse.

"We consider only legal Ada programs" -- please speak for yourself. What is 
in or not in that set of legal Ada programs is a very important part of 
Ada's design (and any language design). I'm not particularly interested in 
the run-time semantics of scalar types, because it is pretty much that of 
the hardware and no amount of language design is going to change that. The 
only thing we can tweak is what is legal and illegal.

It's pretty obvious that you have no interest in useful discourse on this 
topic (which is really too bad, because you have interesting ideas that 
could help out Ada in the long run), so I'm going to do my best to ignore 
this thread in the future.

                                    Randy.





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

* Re: Is this expected behavior or not
  2013-03-19 20:45                                                                 ` Dmitry A. Kazakov
@ 2013-03-19 21:59                                                                   ` J-P. Rosen
  2013-03-20 10:04                                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-03-19 21:59 UTC (permalink / raw)


Le 19/03/2013 21:45, Dmitry A. Kazakov a �crit :
>>> Subtype is a type that inherits some operations (interface) of another
>>> >> type, called "parent type," "base type," "ancestor type" or "supertype."
>> > 
>> > This may be the source of the confusion. What you describe is called
>> > "subtype" in other languages, but this is called "derived type" in Ada.
>> > An Ada subtype is a completely different beast, that does not correspond
>> > to this definition.
> And how is it different?
> 
It is different in that a subtype does NOT inherit operations, it has
the SAME operations as its type.

Proof: a fundamental feature of OOP is that you can redefine inherited
operations. You cannot redefine operations of a subtype to be different
from those of its type.

Note also that a subtype is a property of an object; a value has no
subtype, only a type. Therefore, it would not be possible to dispatch
according to the subtype, since you would not know which operation to
use if the controlling operand is a plain value.

Now, you can argue that these are all more flaws of Ada - or recognize
at last that a subtype is not a different type.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-19 21:37                                                       ` Randy Brukardt
@ 2013-03-20  8:48                                                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-20  8:48 UTC (permalink / raw)


On Tue, 19 Mar 2013 16:37:30 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:vawvqtrqgamw$.1gsl8m14dvk4i.dlg@40tude.net...
>> On Mon, 18 Mar 2013 17:36:31 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:hiybjkhz3p5d.1x6dxfr1ptgcg.dlg@40tude.net...
>>
>>>> But I don't see where I disagree with myself. Contract /= type. You can
>>>> have same contract and different types. What about:
>>>>
>>>>   type Same is new Integer;
>>>
>>> This definitely has a different contract, as it is not compatible with
>>> Integer's contract. Yes, it has the same set of values and operations 
>>> with the same name, profile, and bodies, but it's still a different contract
>>> because the types involved are an intergral part of the contract.
>>
>> See, you just defined a contract in terms of types while using contracts to
>> define type as same/different/non-existent. You cannot have it in both
>> ways.
> 
> If you can't handle recursive definitions, you'll never get very far in 
> programming language design.

Still, the definition you used is broken. Mine is not.

>>>> You also can have different contracts put on the same type in different
>>>> contexts. You can have contracts on something that does not involve types
>>>> at all. Anyway, I fail to see how contracts are relevant here.
>>>
>>> Because types are an important part of a contract (that is, in Ada terms,
>>> the profile).
>>
>> *if* you want to contract a type, *then* that cannot be a part of.
> 
> A type *has* a contract. A contract is made up (in part) of types.

1. *Other* types.

2. To have a contract /= be a part of.

>>> I agree with Georg; Positive is not a type; it *has* a type. Neither is
>>> Integer a type; it *has* a type.
>>
>> Since there is an equivalence between Positive and the type is "has,"
> 
> No, there is not any equivalence. "Type" is just one property of "Positive", 
> and it might have the same value as that of some other subtype (like 
> "Natural").

The equivalence

http://en.wikipedia.org/wiki/Equivalence_relation

is that for each Ada-subtype S there exists a corresponding Ada-type T, and
conversely for each T there exists S.

>> Positive as a name unambiguously refers to that type, i.e. "Positive" is
>> the name of the type. Unless you have other legal name for it. But you
>> don't in Ada. You have absolutely no language means whatsoever to
>> distinguish Positive and the type of. So, what merits has this distinction
>> if it cannot be observed?
> 
> "The type of Positive" unambigiously identifies that property for 
> "Positive". There is not "name" (that is, identifier) associated with that 
> property.

... and there is no way you could find any difference.

>>> (All types in Ada are anonymous.)
>>
>> Great, then let them be, where there belong to, in the celestial spheres,
>> and let us call type something that indeed exists in the language and has 
>> a name.
> 
> Well, if you insist on naming the unnameable, you'll never reach any useful 
> understanding. If you absolutely have to have a name, call it "the type of 
> Positive" or "Positive'Base" (not all types have the 'Base attribute, or you 
> could use that as the name).
> 
> And Positive'Base = Integer'Base = Natural'Base.

But Positive /= Integer /= Natural

Your theory simply does not reflect language facts, thus it is a wrong
theory.

>>> Run-time semantics get added on top of that, but that has no effect on 
>>> the legality of a program, so it is completely orthogonal to the 
>>> type/profile.
>>
>> Legality is irrelevant as we consider only legal Ada programs. There exist
>> legal Ada programs which change their run-time behavior when 'Positive' is
>> replaced by 'Integer' and reverse.
> 
> "We consider only legal Ada programs" -- please speak for yourself.

Yes, I am a programmer, I am not interested in illegal programs.

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



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

* Re: Is this expected behavior or not
  2013-03-19 21:59                                                                   ` J-P. Rosen
@ 2013-03-20 10:04                                                                     ` Dmitry A. Kazakov
  2013-03-20 11:01                                                                       ` J-P. Rosen
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-20 10:04 UTC (permalink / raw)


On Tue, 19 Mar 2013 22:59:22 +0100, J-P. Rosen wrote:

> Le 19/03/2013 21:45, Dmitry A. Kazakov a �crit :
>>>> Subtype is a type that inherits some operations (interface) of another
>>>> >> type, called "parent type," "base type," "ancestor type" or "supertype."
>>> > 
>>> > This may be the source of the confusion. What you describe is called
>>> > "subtype" in other languages, but this is called "derived type" in Ada.
>>> > An Ada subtype is a completely different beast, that does not correspond
>>> > to this definition.
>> And how is it different?
>> 
> It is different in that a subtype does NOT inherit operations, it has
> the SAME operations as its type.

How do you know that they are same? In what sense are they same?

But they are evidently not same:

   procedure Foo (X : out Integer) is
   begin
      X := -1;
   end Foo;
   
when inherited by Positive changes its behavior.

> Proof: a fundamental feature of OOP is that you can redefine inherited
> operations. You cannot redefine operations of a subtype to be different
> from those of its type.

But they are redefined. The compiler adds conversion to the subtype for
each in-argument and conversion from the subtype for each out-argument.
Which is what happens with Foo above the body of

   procedure Foo (X : out Positive)

is the body of

   procedure Foo (X : out Integer) + constraint check.

> Note also that a subtype is a property of an object; a value has no
> subtype, only a type.

No, subtyping is a relation between two types, denoted as T<:S.

Object has no subtype, it has a type. So does a value.

>Therefore, it would not be possible to dispatch
> according to the subtype, since you would not know which operation to
> use if the controlling operand is a plain value.

It is impossible to dispatch on a specific type anyway. Dispatching happens
only on a class-wide type.

Integer and Positive indeed form a class, but Ada, presently, has no type
corresponding to that class, e.g. Integer'Class. If it had, and if you had
an object of the type Integer'Class, then you could dispatch. Which is BTW,
a highly desired improvement which would for example sort out the mess we
have with string types.

> Now, you can argue that these are all more flaws of Ada - or recognize
> at last that a subtype is not a different type.

Not at all. Ada 83 subtypes are consistent with the type model when they
are considered abstract data types, as they surely are.

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



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

* Re: Is this expected behavior or not
  2013-03-20 10:04                                                                     ` Dmitry A. Kazakov
@ 2013-03-20 11:01                                                                       ` J-P. Rosen
  2013-03-20 13:21                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-03-20 11:01 UTC (permalink / raw)


Le 20/03/2013 11:04, Dmitry A. Kazakov a �crit :
>> It is different in that a subtype does NOT inherit operations, it has
>> the SAME operations as its type.
> 
> How do you know that they are same? In what sense are they same?
> 
> But they are evidently not same:
> 
>    procedure Foo (X : out Integer) is
>    begin
>       X := -1;
>    end Foo;
>    
> when inherited by Positive changes its behavior.
They are not inherited! You can call the above Foo with a variable of
type Positive; Constraint_Error is raised after the call when converting
back. But once again, it is the same operation that is called by Integer
and Positive.

>> Proof: a fundamental feature of OOP is that you can redefine inherited
>> operations. You cannot redefine operations of a subtype to be different
>> from those of its type.
> 
> But they are redefined. The compiler adds conversion to the subtype for
> each in-argument and conversion from the subtype for each out-argument.
> Which is what happens with Foo above the body of
> 
>    procedure Foo (X : out Positive)
> 
> is the body of
> 
>    procedure Foo (X : out Integer) + constraint check.
> 
This is not the way it is defined in Ada, and what I said is that the
user cannot redefine Foo for Positive.

>> Note also that a subtype is a property of an object; a value has no
>> subtype, only a type.
> 
> No, subtyping is a relation between two types, denoted as T<:S.
In standard OO speak yes, but that is NOT the meaning in Ada.

> Object has no subtype, it has a type. So does a value.
An object has a subtype that defines a constraint to be checked when
assigning to it.

You may view or describe features of Ada any way you please (I do
sometimes cheat with the official model for explanatory purposes when
I'm teaching), but here we are discussing the official model of Ada, and
what words mean as defined in ISO-8652:2012. The term "subtype" as
defined there is not what you use it for.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-19 21:19                                                           ` Randy Brukardt
@ 2013-03-20 11:21                                                             ` Dmitry A. Kazakov
  2013-03-20 23:57                                                               ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-20 11:21 UTC (permalink / raw)


On Tue, 19 Mar 2013 16:19:54 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:vo941i7imo8t$.1jjjox9r1hkqa.dlg@40tude.net...

>> It is well possible. Consider tag a constraint as array bounds are. Allow
>> constraints (=discriminants) passed independently as compilers already do
>> for array bounds. This gives you array interfaces while keeping arrays as
>> they are, plain arrays.
> 
> No, it's not possible. In order to solve the string problem, we have to 
> decouple the representation and the interface. But for slices, you have to 
> know the representation in order to be able to pass it meaningfully.

You pass dope and reference.
 
> Moreover, the representation is not necessarily an array (UTF-8 encoding is 
> not a normal array if you are using the character interface).

In the dope you have type tag to handle class-wide instances. You will
dispatch to the body which implements indexing for UTF-8 encoded arrays of
characters.

>>> My rough proposed Root_String_Type would be an abstract tagged type,
>>
>> I definitely don't want strings tagged.
> 
> Then forget it. All composite types ought to be tagged; the root of the 
> existing problem is that arrays aren't tagged.

If you use "tagged" in RM sense as a class of types which a tag embedded
into the representation, then no. That is not the problem and I don't want
arrays to have tag. I want array interfaces and an ability to have objects
of the type A'Class where A is an array type. The representation of A'Class
will have tag. The representation of A will not.

>>> but it
>>> wouldn't provide slices directly (it would provide functions for that
>>> purpose). But that's OK, because such a construct would have to be 
>>> alongside
>>> the existing string types; we can't replace or change them in any
>>> significant way and I think that means we'll have to start over.
>>
>> But we can. The point is that the existing type system of Ada is fully
>> compatible with the system I am talking about. There is no compatibility
>> issues.
> 
> You're dreaming - it's not possible. As soon as you change the inheritance 
> rules (which you have to do), you'll break the semantics of derived types 
> (they'll inherit different operations).

I won't change these rules. Remember, in my model they already inherit,
they will keep on doing that, just explicitly rather than implicitly like
now.

> I don't think we 
> need 'Class for access types,

You need them because access types shall implement "access interface." We
need access interface for user-defined referential types.

> because the effect is essentially the same as 
> what we already have for anonymous access types

I don't see why. I want to be able to declare my own type as an access
type:

   type Handle is private access T;
private
   type Handle is record
       Connection : DB_Connection_Handle;
       Table         : Unbounded_String;
       ... -- etc
   end record;

with the semantics of new, Free, dereferencing defined as I wish. And I
want to be able to write a class-wide subprogram which would take both
Handle and some plain access type as a parameter.

This is well possible in the T'Class is constructed by adding type tag.

>> Presently, I am unable to compile my project under any 32-bit system
>> because GNAT compiler needs 3GB an more to instantiate all generics, apart
>> from that this takes 3-4 hours on an i7, and the project has hundreds of
>> meaningless packages which only purpose is to instantiate.
> 
> For someone that hates generics, why would you have so many?

I have:

1. I/O modes of input, output, duplex;
2. Specific values of types: Integer_n, Unsigned_n, String, Wide_String,
IEEE_Float_n;
3. Devices responsible to handle "registers" holding values;
4. Handles to registers;
5. Publishing value change events and monitors of;
6. Much whished, but practically impossible to do, bounded values.

Here you are. On top of that there exist immense problems with explicit
conversions which needed between, say, a handle to a duplex register, when
an output one is expected. It is not just N instances it is also 2**N
combinations of cross operations.

> Maybe you're trying too hard to be Object-Oriented;

I am trying to have it type-safe. It would be just impossible to do in Ada
95. In Ada 2005, which has Java interfaces, it gives what I described. Lack
of MI, which is worked around using generics. I guess that MI would slash
the amount of code by ten. MD would do another tenth. 

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



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

* Re: Is this expected behavior or not
  2013-03-20 11:01                                                                       ` J-P. Rosen
@ 2013-03-20 13:21                                                                         ` Dmitry A. Kazakov
  2013-03-20 23:31                                                                           ` Randy Brukardt
  2013-03-22 10:23                                                                           ` J-P. Rosen
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-20 13:21 UTC (permalink / raw)


On Wed, 20 Mar 2013 12:01:25 +0100, J-P. Rosen wrote:

> Le 20/03/2013 11:04, Dmitry A. Kazakov a �crit :
>>> It is different in that a subtype does NOT inherit operations, it has
>>> the SAME operations as its type.
>> 
>> How do you know that they are same? In what sense are they same?
>> 
>> But they are evidently not same:
>> 
>>    procedure Foo (X : out Integer) is
>>    begin
>>       X := -1;
>>    end Foo;
>>    
>> when inherited by Positive changes its behavior.

> They are not inherited! You can call the above Foo with a variable of
> type Positive; Constraint_Error is raised after the call when converting
> back. But once again, it is the same operation that is called by Integer
> and Positive.

See, same operation applied to same value of same type gives different
result.

This is called UNTYPED.
 
>>> Proof: a fundamental feature of OOP is that you can redefine inherited
>>> operations. You cannot redefine operations of a subtype to be different
>>> from those of its type.
>> 
>> But they are redefined. The compiler adds conversion to the subtype for
>> each in-argument and conversion from the subtype for each out-argument.
>> Which is what happens with Foo above the body of
>> 
>>    procedure Foo (X : out Positive)
>> 
>> is the body of
>> 
>>    procedure Foo (X : out Integer) + constraint check.
>> 
> This is not the way it is defined in Ada,

This is the way it works, so it is the way it is.

> and what I said is that the
> user cannot redefine Foo for Positive.

Which was the core problem with the subtype Prime and the operation 'Succ
the OP reported.

Inheritance as-is composed with a conversion is relatively harmless when
the constraint is a range. But when the constraint is arbitrary it would
break almost everything and it does. This is a hard mathematical fact, no
LRM or ISO has any authority here.

>>> Note also that a subtype is a property of an object; a value has no
>>> subtype, only a type.
>> 
>> No, subtyping is a relation between two types, denoted as T<:S.
> In standard OO speak yes, but that is NOT the meaning in Ada.

The definition is independent on any language. I don't redefine the meaning
of Ada-subtype. I translate Ada's definition into the terms of ADT. In
these terms Ada-subtype is a proper type.

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



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

* Re: Is this expected behavior or not
  2013-03-20 13:21                                                                         ` Dmitry A. Kazakov
@ 2013-03-20 23:31                                                                           ` Randy Brukardt
  2013-03-21  9:08                                                                             ` Dmitry A. Kazakov
  2013-03-22 10:23                                                                           ` J-P. Rosen
  1 sibling, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-20 23:31 UTC (permalink / raw)


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

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1xg9wka6slgit.1q0leacagdeuv.dlg@40tude.net...
> On Wed, 20 Mar 2013 12:01:25 +0100, J-P. Rosen wrote:
>
>> Le 20/03/2013 11:04, Dmitry A. Kazakov a �crit :
>>>> It is different in that a subtype does NOT inherit operations, it has
>>>> the SAME operations as its type.
>>>
>>> How do you know that they are same? In what sense are they same?
>>>
>>> But they are evidently not same:
>>>
>>>    procedure Foo (X : out Integer) is
>>>    begin
>>>       X := -1;
>>>    end Foo;
>>>
>>> when inherited by Positive changes its behavior.
>
>> They are not inherited! You can call the above Foo with a variable of
>> type Positive; Constraint_Error is raised after the call when converting
>> back. But once again, it is the same operation that is called by Integer
>> and Positive.
>
> See, same operation applied to same value of same type gives different
> result.
>
> This is called UNTYPED.

Sounds right to me; by the rules of your useless definitions, you can 
clearly prove that Ada is untyped. Since Integer and Positive are names for 
the same type, with non-type properties involved. Calling this "untyped" 
makes much more sense than trying to claim some sort of inheritance 
relationship (which is almost always the case, inheritance is almost never 
worth the mental energy expended upon it).

To me, this just demostrates the worthlessness of your definitions when 
applied to Ada. Apparently others feel the same way.

...
> Inheritance as-is composed with a conversion is relatively harmless when
> the constraint is a range. But when the constraint is arbitrary it would
> break almost everything and it does. This is a hard mathematical fact, no
> LRM or ISO has any authority here.

The whole idea of "inheritance" has almost no value in any context. It's 
definitely not worth the energy that people (including) have put into it. A 
model where every type started with a clean slate other than predefined 
operations works just as well.

...
> The definition is independent on any language. I don't redefine the 
> meaning
> of Ada-subtype. I translate Ada's definition into the terms of ADT. In
> these terms Ada-subtype is a proper type.

I disagree that Integer is an "ADT" in the first place. There is nothing 
"abstract" about Integer or any numeric type (even using the English meaning 
of "abstract") -- all of the values and operations are known and defined by 
the type declaration. Calling it an "ADT" seems brain-damaged to me; an ADT 
in Ada is a private type or an interface or an abstract type -- there has to 
be something hidden.

In any case, this discussion has run its course. So long as you cling to a 
useless and different terminlogy, we really can't discuss the interesting 
topics, like the value of Integer'Class. This is a useful idea, but not the 
way you describe it. If you claim that it has something useful to do with 
subtypes, you are already so far off the rails that there is nothing to talk 
about. We're not going to jettison 40 years of Ada education and 
understanding just to adopt a model that makes Dmitry more comfortable! So 
I'm done here.

                                          Randy.





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

* Re: Is this expected behavior or not
  2013-03-20 11:21                                                             ` Dmitry A. Kazakov
@ 2013-03-20 23:57                                                               ` Randy Brukardt
  2013-03-21 10:30                                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-20 23:57 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1raubw1sk48ca$.69rdgczvnnf.dlg@40tude.net...
> On Tue, 19 Mar 2013 16:19:54 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:vo941i7imo8t$.1jjjox9r1hkqa.dlg@40tude.net...
>
>>> It is well possible. Consider tag a constraint as array bounds are. 
>>> Allow
>>> constraints (=discriminants) passed independently as compilers already 
>>> do
>>> for array bounds. This gives you array interfaces while keeping arrays 
>>> as
>>> they are, plain arrays.
>>
>> No, it's not possible. In order to solve the string problem, we have to
>> decouple the representation and the interface. But for slices, you have 
>> to
>> know the representation in order to be able to pass it meaningfully.
>
> You pass dope and reference.

You have to know the representation of what you reference in order to access 
it, even after the "dope and reference". The only way to handle differing 
representations is to pass accessor thunks along with the dope, but that 
only allows you to access individual elements. Turning every slice reference 
into a loop of thunk calls is just way to complicated for the usage (which 
is pretty rare, especially if packages like Unbounded_Strings are made 
class-wide).

>> Moreover, the representation is not necessarily an array (UTF-8 encoding 
>> is
>> not a normal array if you are using the character interface).
>
> In the dope you have type tag to handle class-wide instances. You will
> dispatch to the body which implements indexing for UTF-8 encoded arrays of
> characters.

If any dispatching is involved, the syntax ought to be that of a function 
call. That allows indexing but not slicing.

Even if you are willing to confuse users with implicit dispatching, you're 
also talking about turning every slice reference into a loop. The extra 
complication would be intolerable for most vendors.

>>>> My rough proposed Root_String_Type would be an abstract tagged type,
>>>
>>> I definitely don't want strings tagged.
>>
>> Then forget it. All composite types ought to be tagged; the root of the
>> existing problem is that arrays aren't tagged.
>
> If you use "tagged" in RM sense as a class of types which a tag embedded
> into the representation, then no. That is not the problem and I don't want
> arrays to have tag. I want array interfaces and an ability to have objects
> of the type A'Class where A is an array type. The representation of 
> A'Class
> will have tag. The representation of A will not.

Why do you care? String objects are a lot bigger than a tag, so it can't be 
a memory usage concern. The only other place it could possibly matter is 
I/O. But for package like Text_IO, a tag and dispatching is exactly what you 
want, and for 98% of strings, that's what they ultimately get used for. For 
streaming and the like, the representation does not include the tag if you 
stream a specific type. So what's the problem??

Removing a tag from an object is an optimization; I believe every object 
should have a tag and it's up to the compiler how to implement it. It's 
really none of your (the programmer's) business (in the absence of 
representation clauses).

...
>> I don't think we
>> need 'Class for access types,
>
> You need them because access types shall implement "access interface." We
> need access interface for user-defined referential types.

Ada 2012 has user-defined referential types. You can do everything you need 
with plain-old tagged types.

>> because the effect is essentially the same as
>> what we already have for anonymous access types
>
> I don't see why. I want to be able to declare my own type as an access
> type:
>
>   type Handle is private access T;
> private
>   type Handle is record
>       Connection : DB_Connection_Handle;
>       Table         : Unbounded_String;
>       ... -- etc
>   end record;
>
> with the semantics of new, Free, dereferencing defined as I wish.

You can do the latter two in Ada 2012 as it stands; the first can easily be 
simulated with a constructor function. (Oh, that's right, you can't stand 
constructor functions.)

But in any case, this is a bad idea. You don't want to explicitly handle 
memory management in modern programs. Do it under the covers somewhere (like 
in the containers packages); do *not* expose access types.

> And I
> want to be able to write a class-wide subprogram which would take both
> Handle and some plain access type as a parameter.

As I said, no new code should be exposing raw access types. Something like 
the container Cursor type is a much better way to handle the need for 
referential semantics.

...
>> For someone that hates generics, why would you have so many?
>
> I have:
>
> 1. I/O modes of input, output, duplex;

Seems like a runtime parameter, not a compile-time one. (i.e. Mode in the 
I/O packages).

> 2. Specific values of types: Integer_n, Unsigned_n, String, Wide_String, 
> IEEE_Float_n;

Yes, of course, this is the problem that requires generics, mainly building 
things like the Ada containers.

> 3. Devices responsible to handle "registers" holding values;

I don't see how a generic would help here. It is illegal to have most 
representation clauses in a generic body, so I don't see how you could even 
have a generic in this case. (It certainly wouldn't work in Janus/Ada, can't 
talk about GNAT.)

> 4. Handles to registers;

Pretty much the same as the previous. The package involved would be so small 
and there would be so few of them (one for each kind of native register 
type) that I'd just copy the text and do a block substitution to make a new 
one. Generics would just get in the way (and add overhead on a compiler that 
does sharing, like Janus/Ada).

> 5. Publishing value change events and monitors of;

Maybe, if you need them to work on multiple types. Seems like a sort of 
container, to me.

> 6. Much whished, but practically impossible to do, bounded values.

Seems like that fits under #2 (it's not possible to do these without knowing 
the underlying representation, unless you're willing to make them very 
expensive with tons of barely necessary exception handlers). Here again, I'd 
make a package for each such type that I needed. (That's precisely how this 
issue is handled in the Janus/Ada compiler -- no generics in sight.)

 > Here you are. On top of that there exist immense problems with explicit
> conversions which needed between, say, a handle to a duplex register, when
> an output one is expected. It is not just N instances it is also 2**N
> combinations of cross operations.

Again, I don't see any good reason to try to separate these things.

>> Maybe you're trying too hard to be Object-Oriented;
>
> I am trying to have it type-safe. It would be just impossible to do in Ada
> 95. In Ada 2005, which has Java interfaces, it gives what I described. 
> Lack
> of MI, which is worked around using generics. I guess that MI would slash
> the amount of code by ten. MD would do another tenth.

It's not worth it to be type-safe in this way. Especially as 
preconditions/postconditions combined with static analysis give the same 
effect (compile time checking) with 10% of the work. There definitely is 
such a thing as being too type-safe. Of course, YMMV.

                                                      Randy.





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

* Re: Is this expected behavior or not
  2013-03-20 23:31                                                                           ` Randy Brukardt
@ 2013-03-21  9:08                                                                             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-21  9:08 UTC (permalink / raw)


On Wed, 20 Mar 2013 18:31:29 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1xg9wka6slgit.1q0leacagdeuv.dlg@40tude.net...
>> On Wed, 20 Mar 2013 12:01:25 +0100, J-P. Rosen wrote:
>>
>>> Le 20/03/2013 11:04, Dmitry A. Kazakov a 嚙踝蕭it :
>>>>> It is different in that a subtype does NOT inherit operations, it has
>>>>> the SAME operations as its type.
>>>>
>>>> How do you know that they are same? In what sense are they same?
>>>>
>>>> But they are evidently not same:
>>>>
>>>>    procedure Foo (X : out Integer) is
>>>>    begin
>>>>       X := -1;
>>>>    end Foo;
>>>>
>>>> when inherited by Positive changes its behavior.
>>
>>> They are not inherited! You can call the above Foo with a variable of
>>> type Positive; Constraint_Error is raised after the call when converting
>>> back. But once again, it is the same operation that is called by Integer
>>> and Positive.
>>
>> See, same operation applied to same value of same type gives different
>> result.
>>
>> This is called UNTYPED.
> 
> Sounds right to me; by the rules of your useless definitions, you can 
> clearly prove that Ada is untyped.

Nope. A language is untyped only if no typed interpretation of its
semantics exists. J-P gave an untyped interpretation of Ada's Positive. I
proposed a typed one. Thus, Ada is typed.

[...]
> To me, this just demostrates the worthlessness of your definitions when 
> applied to Ada. Apparently others feel the same way.

Sorry, that is not mine definitions, it is *your* worthy definition
according to which *same* operation on *same* value of *same* type yields
*different* results.

>> Inheritance as-is composed with a conversion is relatively harmless when
>> the constraint is a range. But when the constraint is arbitrary it would
>> break almost everything and it does. This is a hard mathematical fact, no
>> LRM or ISO has any authority here.
> 
> The whole idea of "inheritance" has almost no value in any context. It's 
> definitely not worth the energy that people (including) have put into it. A 
> model where every type started with a clean slate other than predefined 
> operations works just as well.

Once you create an Ada subtype you inherit operations of the base. If you
don't like it, you should be the first for allowing at least overriding
inherited operations, when they become junk as in the case of Prime'Succ.
You should also be in favor for means to specify what should be inherited.
The only mechanism for this I know is explicit interfaces.

>> The definition is independent on any language. I don't redefine the meaning
>> of Ada-subtype. I translate Ada's definition into the terms of ADT. In
>> these terms Ada-subtype is a proper type.
> 
> I disagree that Integer is an "ADT" in the first place. There is nothing 
> "abstract" about Integer or any numeric type (even using the English meaning 
> of "abstract") -- all of the values and operations are known and defined by 
> the type declaration. Calling it an "ADT" seems brain-damaged to me; an ADT 
> in Ada is a private type or an interface or an abstract type -- there has to 
> be something hidden.

Abstract in ADT means that the specification is abstracted from the
implementation.

Anyway, is it only abstractness you are against? From your posts I have an
impression that Integer is not only non-"abstract," but also not a "type,"
and possibly not even "data."

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



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

* Re: Is this expected behavior or not
  2013-03-20 23:57                                                               ` Randy Brukardt
@ 2013-03-21 10:30                                                                 ` Dmitry A. Kazakov
  2013-03-21 23:27                                                                   ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-21 10:30 UTC (permalink / raw)


On Wed, 20 Mar 2013 18:57:58 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1raubw1sk48ca$.69rdgczvnnf.dlg@40tude.net...
>> On Tue, 19 Mar 2013 16:19:54 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:vo941i7imo8t$.1jjjox9r1hkqa.dlg@40tude.net...
>>
>>>> It is well possible. Consider tag a constraint as array bounds are. Allow
>>>> constraints (=discriminants) passed independently as compilers already 
>>>> do for array bounds. This gives you array interfaces while keeping arrays 
>>>> as they are, plain arrays.
>>>
>>> No, it's not possible. In order to solve the string problem, we have to
>>> decouple the representation and the interface. But for slices, you have 
>>> to know the representation in order to be able to pass it meaningfully.
>>
>> You pass dope and reference.
> 
> You have to know the representation of what you reference in order to access 
> it, even after the "dope and reference".

Why? So long the dope contains the type tag, the string object is
class-wide. For a class-wide object I should not care about
representations. Representations to be handled after ultimate dispatch
happens. The specific body will know the representation statically.

>>> Moreover, the representation is not necessarily an array (UTF-8 encoding is
>>> not a normal array if you are using the character interface).
>>
>> In the dope you have type tag to handle class-wide instances. You will
>> dispatch to the body which implements indexing for UTF-8 encoded arrays of
>> characters.
> 
> If any dispatching is involved, the syntax ought to be that of a function 
> call. That allows indexing but not slicing.

Depends on whether slicing to produce a class-wide slice object or a
specific type object. I cannot tell what would be better, but in both cases
slicing should be a proper operation (two operations, actually, for l- and
r-values).

> Even if you are willing to confuse users with implicit dispatching, you're 
> also talking about turning every slice reference into a loop.

I don't see why. When the slice object happens to be class-wide, you have a
dope with a tag, bounds and a reference to some yet-to-be-discovered
representation. When the slice is specific, you have a dope with bounds and
a reference to some statically known representation.

>>>>> My rough proposed Root_String_Type would be an abstract tagged type,
>>>>
>>>> I definitely don't want strings tagged.
>>>
>>> Then forget it. All composite types ought to be tagged; the root of the
>>> existing problem is that arrays aren't tagged.
>>
>> If you use "tagged" in RM sense as a class of types which a tag embedded
>> into the representation, then no. That is not the problem and I don't want
>> arrays to have tag. I want array interfaces and an ability to have objects
>> of the type A'Class where A is an array type. The representation of 
>> A'Class will have tag. The representation of A will not.
> 
> Why do you care? String objects are a lot bigger than a tag, so it can't be 
> a memory usage concern. The only other place it could possibly matter is 
> I/O. But for package like Text_IO, a tag and dispatching is exactly what you 
> want, and for 98% of strings, that's what they ultimately get used for. For 
> streaming and the like, the representation does not include the tag if you 
> stream a specific type. So what's the problem??

The problem is slicing and interfacing to other languages. Tagged string
will require copying in and/or out each time you pass a slice to a
subprogram. On top of that tagged types are by-reference which contradicts
to copying.

> Removing a tag from an object is an optimization; I believe every object 
> should have a tag and it's up to the compiler how to implement it. It's 
> really none of your (the programmer's) business (in the absence of 
> representation clauses).

Only class-wide objects, you mean. Specific object need no tags and those
with representation aspects shall not have it.

As for considering it optimization, I really want this rather in the
contract. Because the mechanism of adding some information to a class-wide
object looks very promising beyond tags. We could use it on so many other
cases:

1. Dimensioned values
2. Array bounds
3. Matrix dimensions
4. Storage pool reference in a pointer object
...

>>> I don't think we
>>> need 'Class for access types,
>>
>> You need them because access types shall implement "access interface." We
>> need access interface for user-defined referential types.
> 
> Ada 2012 has user-defined referential types. You can do everything you need 
> with plain-old tagged types.

Like having it 16-bit long? I don't like when the language mandates
representation of use-defined types. It looks more like a discount center.

> But in any case, this is a bad idea. You don't want to explicitly handle 
> memory management in modern programs. Do it under the covers somewhere (like 
> in the containers packages); do *not* expose access types.

Container libraries need to be implemented as well. I don't want to expose
access type, I want referential semantics.

>> And I
>> want to be able to write a class-wide subprogram which would take both
>> Handle and some plain access type as a parameter.
> 
> As I said, no new code should be exposing raw access types. Something like 
> the container Cursor type is a much better way to handle the need for 
> referential semantics.

But 4.1.5 does not hide access types. On the contrary it mandates access
type as the discriminant.

> ...
>>> For someone that hates generics, why would you have so many?
>>
>> I have:
>>
>> 1. I/O modes of input, output, duplex;
> 
> Seems like a runtime parameter, not a compile-time one. (i.e. Mode in the 
> I/O packages).

No, it is intended for static checks. E.g. you cannot apply certain
operations to an input object.

>> 2. Specific values of types: Integer_n, Unsigned_n, String, Wide_String, 
>> IEEE_Float_n;
> 
> Yes, of course, this is the problem that requires generics, mainly building 
> things like the Ada containers.
> 
>> 3. Devices responsible to handle "registers" holding values;
> 
> I don't see how a generic would help here.

Each device instantiates its own register object types. The pattern looks
like

   generic
      type Base_Type is new ... -- Some device specific base
   package Generic_Input_Scalar_Dimensioned_Whatever is
      type Device_Register_Type is new Base_Type
         and Input_Interface
         and Scalar_Interface
         ...
         with private;
   
It is only needed because there is no MI. It also introduces some run-time
overhead as it is turned upside down. Actually the device-specific stuff
should have been added to some type/mode specific implementation.

But that is a minor nuisance comparing to geometric explosion of packages
and their instances.

>> 4. Handles to registers;
> 
> Pretty much the same as the previous. The package involved would be so small 
> and there would be so few of them (one for each kind of native register 
> type) that I'd just copy the text and do a block substitution to make a new 
> one. Generics would just get in the way (and add overhead on a compiler that 
> does sharing, like Janus/Ada).

It is not so small, because it has to implement a number of operations. The
problem is that there are hundreds of such generic packages containing
meaningless cut-and-paste code like

   function Get_Name (Register : Register_Handle) return String is
   begin
      return Register.Ptr.Get_Name;
   end Get_Name;
 
>> 5. Publishing value change events and monitors of;
> 
> Maybe, if you need them to work on multiple types. Seems like a sort of 
> container, to me.

But, again, more than one. It a multiplicator. For an input Integer_16
handle I need a monitor object which spits an Integer_16 values. Once a
single generic comes inside it explodes like a particle in the collider.

>> 6. Much whished, but practically impossible to do, bounded values.
> 
> Seems like that fits under #2 (it's not possible to do these without knowing 
> the underlying representation, unless you're willing to make them very 
> expensive with tons of barely necessary exception handlers). Here again, I'd 
> make a package for each such type that I needed. (That's precisely how this 
> issue is handled in the Janus/Ada compiler -- no generics in sight.)

I cannot write so many packages manually. It will be many thousands.
Generics offer at least some help with code reuse.

>  > Here you are. On top of that there exist immense problems with explicit
>> conversions which needed between, say, a handle to a duplex register, when
>> an output one is expected. It is not just N instances it is also 2**N
>> combinations of cross operations.
> 
> Again, I don't see any good reason to try to separate these things.

For type safety. I want that a program that tries to send a string value to
a digital analogue input would not compile rather than fail at run-time
[which could be extremely expensive].

It turned much harder than I thought it initially.

>>> Maybe you're trying too hard to be Object-Oriented;
>>
>> I am trying to have it type-safe. It would be just impossible to do in Ada
>> 95. In Ada 2005, which has Java interfaces, it gives what I described. Lack
>> of MI, which is worked around using generics. I guess that MI would slash
>> the amount of code by ten. MD would do another tenth.
> 
> It's not worth it to be type-safe in this way. Especially as 
> preconditions/postconditions combined with static analysis give the same 
> effect (compile time checking) with 10% of the work.

Even if it were compile-time it would require same representation for all
involved objects. How would I do it for Unsigned_1 and String?

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



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

* Re: Is this expected behavior or not
  2013-03-21 10:30                                                                 ` Dmitry A. Kazakov
@ 2013-03-21 23:27                                                                   ` Randy Brukardt
  2013-03-22 16:07                                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-21 23:27 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:i93qv6ba3bv0.wuicbsmfm5ha.dlg@40tude.net...
> On Wed, 20 Mar 2013 18:57:58 -0500, Randy Brukardt wrote:
...
>> Even if you are willing to confuse users with implicit dispatching, 
>> you're
>> also talking about turning every slice reference into a loop.
>
> I don't see why. When the slice object happens to be class-wide, you have 
> a
> dope with a tag, bounds and a reference to some yet-to-be-discovered
> representation. When the slice is specific, you have a dope with bounds 
> and
> a reference to some statically known representation.

The underlying model of a slice is an implicit loop. We already have to use 
loops to implement some slices in existing Ada; there is no possibility of 
eliminating that. That's because ultimately everything is done on machine 
objects (bytes, words, dwords, etc.) and you always need a loop if you are 
going to operate on more than one. Of course, if you know the 
representation, you can get away with special-case loops (like a block 
move), but if you don't know the representation of the elements (or how the 
indexing works), a loop is the only possible implementation.

Because of that, there is almost no value to slicing operations unless you 
know the representation and can use block move instructions. Otherwise, you 
are setting up a loop of dispatching operations, one element at a time. It's 
dubious that this is worth special language support.

There's nothing that you can do with a slice that you can't do with a loop, 
and usually the loop is easier to write and understand. The only advantage 
of the slice is the optimized code that it can produce, and that's gone if 
you don't have the representation. (The whole idea of slices was a mistake 
that probably shouldn't have been in the language in the first place -- it 
caused a reliance on not very good string processing instead of providing a 
reasonable mechanism from the beginning.)

...
>> Why do you care? String objects are a lot bigger than a tag, so it can't 
>> be
>> a memory usage concern. The only other place it could possibly matter is
>> I/O. But for package like Text_IO, a tag and dispatching is exactly what 
>> you
>> want, and for 98% of strings, that's what they ultimately get used for. 
>> For
>> streaming and the like, the representation does not include the tag if 
>> you
>> stream a specific type. So what's the problem??
>
> The problem is slicing and interfacing to other languages. Tagged string
> will require copying in and/or out each time you pass a slice to a
> subprogram. On top of that tagged types are by-reference which contradicts
> to copying.

Slicing is already impossible for the case that we're talking about, and 
interface to foreign language already has to be done through special types. 
(Using a type that doesn't have convention C is wrong for C interfacing, 
although your current compiler might allow it, there is no reason to assume 
another has the same rules.)

Clearly, types with an appropriate representation clause need to follow that 
clause (or be rejected), but again I ask why do you care how types that are 
going to be used purely by Ada (and that had better be most of them) are 
implemented??

>> Removing a tag from an object is an optimization; I believe every object
>> should have a tag and it's up to the compiler how to implement it. It's
>> really none of your (the programmer's) business (in the absence of
>> representation clauses).
>
> Only class-wide objects, you mean. Specific object need no tags and those
> with representation aspects shall not have it.

No I mean all objects. It should be none of your business how the compiler 
implements objects -- any objects -- you ought to want the compiler to do 
the best job it can, not put arbitrary and possibly counter-productive 
restrictions on it. If you need a particular representation, then you need 
to give a representation clause. Otherwise, leave the compiler alone.

> As for considering it optimization, I really want this rather in the
> contract. Because the mechanism of adding some information to a class-wide
> object looks very promising beyond tags. We could use it on so many other
> cases:
>
> 1. Dimensioned values
> 2. Array bounds
> 3. Matrix dimensions
> 4. Storage pool reference in a pointer object
> ...

None of the above makes any sense whatsoever. We need all of those things in 
the object in order to generate code. (Janus/Ada uses a single 
representation for all objects of a type, and you don't have enough money to 
change that.) It's possible in limited circumstances to avoid that 
(statically constrained arrays come to mind), but every such special case 
greatly increases the complication of a compiler.

I suspect that if your model became the law of the land, compilers would 
generate very bad code for any cases like the ones you want, and you 
wouldn't be able to use the result anyway. And again, I don't think you have 
enough money to change that situation (maybe if I won the Powerball I 
could...)

>>>> I don't think we
>>>> need 'Class for access types,
>>>
>>> You need them because access types shall implement "access interface." 
>>> We
>>> need access interface for user-defined referential types.
>>
>> Ada 2012 has user-defined referential types. You can do everything you 
>> need
>> with plain-old tagged types.
>
> Like having it 16-bit long? I don't like when the language mandates
> representation of use-defined types. It looks more like a discount center.

If you *really* need a 16-bit pointer, that means you have truly critical 
time/space needs. And in that case, you really need to dump everything 
modern (OOP, interfaces, etc.) in the trash can and write basic Ada 83-style 
ADT code, without any attempt at anything special. Because the overheads 
associated with OOP (especially any form of multiple inheritance) are always 
going to cost many times in time and space your "16-bit pointer". A compiler 
could fake it, but all that you've done is moved the costs into a corner 
where they're less obvious. They didn't magically go away.

Besides, if the sort of uses you are asking about get prominence, then 
clearly compiler writers will try to make their implementations more 
efficient (as AdaCore has done with finalization). There is not fundamental 
reason that a compiler writer with sufficient motivation couldn't leave the 
tags out of tagged objects (that was a goal for the design of Ada 9x, and I 
believe it is possible). There's no reason to invent new semantics when the 
existing semantics is good enough.

>> But in any case, this is a bad idea. You don't want to explicitly handle
>> memory management in modern programs. Do it under the covers somewhere 
>> (like
>> in the containers packages); do *not* expose access types.
>
> Container libraries need to be implemented as well. I don't want to expose
> access type, I want referential semantics.

And that's the point of 4.1.5. The only thing you can't do is write "new" 
that way, but calling a function to do that doesn't seem that bad.

>>> And I
>>> want to be able to write a class-wide subprogram which would take both
>>> Handle and some plain access type as a parameter.
>>
>> As I said, no new code should be exposing raw access types. Something 
>> like
>> the container Cursor type is a much better way to handle the need for
>> referential semantics.
>
> But 4.1.5 does not hide access types. On the contrary it mandates access
> type as the discriminant.

Ahh, but that was a case where the "existing semantics" was good enough so 
we didn't create a new thing. This is a very special access type, one that 
almost never can be copied -- for practical purposes it can only be 
dereferenced. That's what we needed. Note that there is no intent that 
anyone ever create an object for this access type (and that is where all of 
the problems lie). It just has the syntax of an access type so we didn't 
have to invent a new thing to get dereferencing.


>> ...
>>>> For someone that hates generics, why would you have so many?

Thanks for the lengthy explanation. I'm not going to comment on it 
individually anymore, because one is always on thin ice talking about 
another's code without knowing all of the issues involved, and there seems 
to be a summary point.

...
>>>> Maybe you're trying too hard to be Object-Oriented;
>>>
>>> I am trying to have it type-safe. It would be just impossible to do in 
>>> Ada
>>> 95. In Ada 2005, which has Java interfaces, it gives what I described. 
>>> Lack
>>> of MI, which is worked around using generics. I guess that MI would 
>>> slash
>>> the amount of code by ten. MD would do another tenth.
>>
>> It's not worth it to be type-safe in this way. Especially as
>> preconditions/postconditions combined with static analysis give the same
>> effect (compile time checking) with 10% of the work.
>
> Even if it were compile-time it would require same representation for all
> involved objects. How would I do it for Unsigned_1 and String?

I don't see this necessarily. You certainly can use dispatching to support 
different representations.

But I still think you are trying too hard to avoid run-time checks. I think 
these need a balance, especially as modern static analyzers can remove the 
vast majority of them (or warn that they might fail, which is a cause for 
concern). (This is assuming use of Pre/Post, of course.) I realize some 
systems have to be locked down without run-time checks because of outside 
reliability requirements, but these systems can't have complex systems of 
generics (or usually have any dispatching or memory management, either). 
Ada's type system isn't powerful enough to push everything to static checks, 
and indeed I'm dubious that any practical system could be that powerful. 
Giant edifices of generics and/or interfaces are essentially impossible to 
understand and debug (and in the margin, compile). Simplify! Simplify! I'd 
rather use a few run-time checks and a few run-time parameters than end up 
with dozens of types and packages.

                              Randy.





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

* Re: Is this expected behavior or not
  2013-03-20 13:21                                                                         ` Dmitry A. Kazakov
  2013-03-20 23:31                                                                           ` Randy Brukardt
@ 2013-03-22 10:23                                                                           ` J-P. Rosen
  2013-03-22 14:54                                                                             ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-03-22 10:23 UTC (permalink / raw)


Le 20/03/2013 14:21, Dmitry A. Kazakov a �crit :

> See, same operation applied to same value of same type gives different
> result.
> 
> This is called UNTYPED.
No, it is not the operation that gives different result, it's the
assignment of a value that is incompatible with the variable's
constraint that raises C_E.

>>> No, subtyping is a relation between two types, denoted as T<:S.
>> In standard OO speak yes, but that is NOT the meaning in Ada.
> 
> The definition is independent on any language. I don't redefine the meaning
> of Ada-subtype. I translate Ada's definition into the terms of ADT. In
> these terms Ada-subtype is a proper type.
> 
The theory of ADT has no notion of subtypes (Ada definition). Therefore,
you can't translate Ada's subtypes into the terms of ADT. You insist on
subtypes being types in a desperate effort to map them to ADT, but
sorry, it is not possible. They are different.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-22 10:23                                                                           ` J-P. Rosen
@ 2013-03-22 14:54                                                                             ` Dmitry A. Kazakov
  2013-03-22 22:18                                                                               ` J-P. Rosen
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-22 14:54 UTC (permalink / raw)


On Fri, 22 Mar 2013 11:23:09 +0100, J-P. Rosen wrote:

> Le 20/03/2013 14:21, Dmitry A. Kazakov a �crit :
> 
>> See, same operation applied to same value of same type gives different
>> result.
>> 
>> This is called UNTYPED.

> No, it is not the operation that gives different result, it's the
> assignment of a value that is incompatible with the variable's
> constraint that raises C_E.

There is no assignment in my example. Assignment is in the *body* of the
operation Foo.

The effect is different when Foo is called on a variable of Integer vs.
Positive "non-types."

Are you saying that one have to look into the bodies, on top of having it
untyped?

And what is so special about assignments?

> The theory of ADT has no notion of subtypes (Ada definition).

There is nothing special in Ada-subtypes. They are just ADTs.

> Therefore,
> you can't translate Ada's subtypes into the terms of ADT.

I just did it.

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



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

* Re: Is this expected behavior or not
  2013-03-21 23:27                                                                   ` Randy Brukardt
@ 2013-03-22 16:07                                                                     ` Dmitry A. Kazakov
  2013-03-22 20:10                                                                       ` Shark8
  2013-03-23  2:33                                                                       ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-22 16:07 UTC (permalink / raw)


On Thu, 21 Mar 2013 18:27:22 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:i93qv6ba3bv0.wuicbsmfm5ha.dlg@40tude.net...
>> On Wed, 20 Mar 2013 18:57:58 -0500, Randy Brukardt wrote:
> ...
>>> Even if you are willing to confuse users with implicit dispatching, you're
>>> also talking about turning every slice reference into a loop.

>> I don't see why. When the slice object happens to be class-wide, you have 
>> a dope with a tag, bounds and a reference to some yet-to-be-discovered
>> representation. When the slice is specific, you have a dope with bounds 
>> and a reference to some statically known representation.
> 
> The underlying model of a slice is an implicit loop. We already have to use 
> loops to implement some slices in existing Ada; there is no possibility of 
> eliminating that. That's because ultimately everything is done on machine 
> objects (bytes, words, dwords, etc.) and you always need a loop if you are 
> going to operate on more than one.

I still don't understand why is it relevant. Ada already has "loops" you
are talking about for String and Wide_String. Why cannot you use them for
their representations after selecting through dispatch?

> Because of that, there is almost no value to slicing operations unless you 
> know the representation and can use block move instructions.

I want to be able to pass a slice to Put_Line without copying.

> There's nothing that you can do with a slice that you can't do with a loop, 
> and usually the loop is easier to write and understand.

Are you suggesting to call Put from a loop instead of Put_Line? I Don't
want the language forcing me doing that.

>>> Why do you care? String objects are a lot bigger than a tag, so it can't be
>>> a memory usage concern. The only other place it could possibly matter is
>>> I/O. But for package like Text_IO, a tag and dispatching is exactly what you
>>> want, and for 98% of strings, that's what they ultimately get used for. For
>>> streaming and the like, the representation does not include the tag if you
>>> stream a specific type. So what's the problem??
>>
>> The problem is slicing and interfacing to other languages. Tagged string
>> will require copying in and/or out each time you pass a slice to a
>> subprogram. On top of that tagged types are by-reference which contradicts
>> to copying.
> 
> Slicing is already impossible for the case that we're talking about,

?

Normal strings have slices and should continue to have them.

> and 
> interface to foreign language already has to be done through special types. 

Which should certainly be in the same class! There is no semantic reason
why char_array should not be considered string.

> Clearly, types with an appropriate representation clause need to follow that 
> clause (or be rejected), but again I ask why do you care how types that are 
> going to be used purely by Ada (and that had better be most of them) are 
> implemented??

Because representation must be controlled by programmer, not by the
language. It should be possible to declare a string object of *any*
representation whatsoever. If the compiler does not know how to implement
operations on this representation it should ask me, the programmer, to
implement them.

>>> Removing a tag from an object is an optimization; I believe every object
>>> should have a tag and it's up to the compiler how to implement it. It's
>>> really none of your (the programmer's) business (in the absence of
>>> representation clauses).
>>
>> Only class-wide objects, you mean. Specific object need no tags and those
>> with representation aspects shall not have it.
> 
> No I mean all objects. It should be none of your business how the compiler 
> implements objects

On the contrary, the compiler is free to choose a representation under the
constraints specified by the programmer. I don't want Ada to become C#. 

>> As for considering it optimization, I really want this rather in the
>> contract. Because the mechanism of adding some information to a class-wide
>> object looks very promising beyond tags. We could use it on so many other
>> cases:
>>
>> 1. Dimensioned values
>> 2. Array bounds
>> 3. Matrix dimensions
>> 4. Storage pool reference in a pointer object
>> ...
> 
> None of the above makes any sense whatsoever. We need all of those things in 
> the object in order to generate code.

So, you want to describe all possible problem domains in the RM? The RM
should know that a matrix of 2 rows and 5 columns can be multiplied to a
5x8 matrix, but not to a 8x8 matrix? Good luck with that!

> I suspect that if your model became the law of the land, compilers would 
> generate very bad code for any cases like the ones you want, and you 
> wouldn't be able to use the result anyway.

Nobody tried. But I doubt it. My proposals have a goal to significantly
simplify the language. Ada 2005 and 2012 added a huge number of special
cases requiring special treatment. That surely complicates optimization of
Ada programs which is already not great. Smaller and more regular language
would be easier to optimize.

>>>>> I don't think we need 'Class for access types,
>>>>
>>>> You need them because access types shall implement "access interface." 
>>>> We need access interface for user-defined referential types.
>>>
>>> Ada 2012 has user-defined referential types. You can do everything you 
>>> need with plain-old tagged types.
>>
>> Like having it 16-bit long? I don't like when the language mandates
>> representation of use-defined types. It looks more like a discount center.
> 
> If you *really* need a 16-bit pointer, that means you have truly critical 
> time/space needs.

Not necessarily. It could be because the thing need to be atomic, or
because I wanted to marshal it. The programmer may have his reasons.

> And in that case, you really need to dump everything 
> modern (OOP, interfaces, etc.) in the trash can and write basic Ada 83-style 
> ADT code, without any attempt at anything special. Because the overheads 
> associated with OOP (especially any form of multiple inheritance) are always 
> going to cost many times in time and space your "16-bit pointer". A compiler 
> could fake it, but all that you've done is moved the costs into a corner 
> where they're less obvious. They didn't magically go away.

This is a totally bogus argument. OO imposes no overhead on specific types.
It does on class-wide objects, which simply non-existent in Ada 83. If you
implemented class-wide objects on top of Ada 83 objects you would get
exactly same overhead or more.
 
> Besides, if the sort of uses you are asking about get prominence, then 
> clearly compiler writers will try to make their implementations more 
> efficient (as AdaCore has done with finalization). There is not fundamental 
> reason that a compiler writer with sufficient motivation couldn't leave the 
> tags out of tagged objects (that was a goal for the design of Ada 9x, and I 
> believe it is possible). There's no reason to invent new semantics when the 
> existing semantics is good enough.

Nobody proposes to change tagged types. The idea is to add classes to
non-tagged types by adding tag to the class-wide object while keeping
specific objects as-is.

>>> But in any case, this is a bad idea. You don't want to explicitly handle
>>> memory management in modern programs. Do it under the covers somewhere 
>>> (like in the containers packages); do *not* expose access types.
>>
>> Container libraries need to be implemented as well. I don't want to expose
>> access type, I want referential semantics.
> 
> And that's the point of 4.1.5. The only thing you can't do is write "new"

(what about 'Access? What about Unchecked_Deallocation?)

> that way, but calling a function to do that doesn't seem that bad.

How do I put such a reference in an array, for example? 4.1.5 would be
extremely difficult to use for intended purpose.

>>>> And I
>>>> want to be able to write a class-wide subprogram which would take both
>>>> Handle and some plain access type as a parameter.
>>>
>>> As I said, no new code should be exposing raw access types. Something 
>>> like the container Cursor type is a much better way to handle the need for
>>> referential semantics.
>>
>> But 4.1.5 does not hide access types. On the contrary it mandates access
>> type as the discriminant.
> 
> Ahh, but that was a case where the "existing semantics" was good enough so 
> we didn't create a new thing. This is a very special access type, one that 
> almost never can be copied -- for practical purposes it can only be 
> dereferenced. That's what we needed. Note that there is no intent that 
> anyone ever create an object for this access type (and that is where all of 
> the problems lie). It just has the syntax of an access type so we didn't 
> have to invent a new thing to get dereferencing.

You have a very specific use case in mind, namely containers. There is a
whole world outside that, for which what you said is untrue, e.g. for smart
pointers. The thing not only exposes access, it also exposes the target
type. For smart pointers and handles you might what to hide both. Consider
a handle to a file. You certainly don't want to make File_Descriptor it
points to, visible. You want the handle to implement file I/O interface
routed privately to the descriptor. You also want handles be copyiable and
comparable, but treated as references to some opaque limited object.

>>>>> Maybe you're trying too hard to be Object-Oriented;
>>>>
>>>> I am trying to have it type-safe. It would be just impossible to do in 
>>>> Ada 95. In Ada 2005, which has Java interfaces, it gives what I described. 
>>>> Lack of MI, which is worked around using generics. I guess that MI would 
>>>> slash the amount of code by ten. MD would do another tenth.
>>>
>>> It's not worth it to be type-safe in this way. Especially as
>>> preconditions/postconditions combined with static analysis give the same
>>> effect (compile time checking) with 10% of the work.
>>
>> Even if it were compile-time it would require same representation for all
>> involved objects. How would I do it for Unsigned_1 and String?
> 
> I don't see this necessarily. You certainly can use dispatching to support 
> different representations.

No way. Consider operation Send:

   procedure Send (To : in out Register; Value : Unsigned_1);

   procedure Send (To : in out Register; Value : String);

It cannot dispatch! Firstly, Unsigned_1 and String are not in the same
class. Secondly, even if they were, it would be MD! So, you need MI and MD
to make it happen. Without them, poor man's solution is messing with
generics.

> But I still think you are trying too hard to avoid run-time checks.

If I weren't, I would use Perl, not Ada. I favor Ada exactly because it
gives me static checks. It is sad to see Ada drifting towards run-time /
dynamic-typing junk.

> I think 
> these need a balance, especially as modern static analyzers can remove the 
> vast majority of them (or warn that they might fail, which is a cause for 
> concern).

It is not about removing checks, though performance is a concern too. The
major problem is that failed checks must be flagged as errors. You are a
compiler writer, I am designing automation systems. To me run-time check is
much too late. A fault can break real things, apart from maintenance.
Imagine Claw running on an oil platform. Do you own a helicopter?

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



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

* Re: Is this expected behavior or not
  2013-03-22 16:07                                                                     ` Dmitry A. Kazakov
@ 2013-03-22 20:10                                                                       ` Shark8
  2013-03-22 20:51                                                                         ` Dmitry A. Kazakov
  2013-03-23  2:33                                                                       ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-22 20:10 UTC (permalink / raw)
  Cc: mailbox

On Friday, March 22, 2013 10:07:51 AM UTC-6, Dmitry A. Kazakov wrote:
> On Thu, 21 Mar 2013 18:27:22 -0500, Randy Brukardt wrote:
> 
> > But I still think you are trying too hard to avoid run-time checks.
> 
> If I weren't, I would use Perl, not Ada. I favor Ada exactly because it
> gives me static checks. It is sad to see Ada drifting towards run-time /
> dynamic-typing junk.

Runtime-typing and dynamic-typing are two different things, no? (As I understand, dynamic-typing could be illustrated with PHP which plays fast and loose with items [string "5" <--> integer 5 or float 5.0], whereas run-time typing could be illustrated with Delphi and its RTTI. {The RTTI can be used to emulate dynamic-typing, even implicitly in some cases IIRC, but that is a far cry from the mashed-potatoes-typing {everything is everything else, except on error which is usually 0 and then converted to the type of 'everything' needed} of PHP}).

Ada has always had run-time checking: I mean consider a type INPUTS {say for enumerating inputs from a menu-driven application of range '0'..'9'} or enumerations where we could do something like

Function Prompt( items: menu ) Return INPUTS is
 Result: INPUT; 
begin
 -- loop
 -- display prompt
 -- get user's input string/character
 -- assign conversion using INPUT'Value to Result
 -- exit when the above conversion is valid [otherwise handle exception]
 -- end loop
 return result;
end Prompt;



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

* Re: Is this expected behavior or not
  2013-03-22 20:10                                                                       ` Shark8
@ 2013-03-22 20:51                                                                         ` Dmitry A. Kazakov
  2013-03-22 23:34                                                                           ` Robert A Duff
  2013-03-23  2:29                                                                           ` Nasser M. Abbasi
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-22 20:51 UTC (permalink / raw)


On Fri, 22 Mar 2013 13:10:18 -0700 (PDT), Shark8 wrote:

> On Friday, March 22, 2013 10:07:51 AM UTC-6, Dmitry A. Kazakov wrote:
>> On Thu, 21 Mar 2013 18:27:22 -0500, Randy Brukardt wrote:
>> 
>>> But I still think you are trying too hard to avoid run-time checks.
>> 
>> If I weren't, I would use Perl, not Ada. I favor Ada exactly because it
>> gives me static checks. It is sad to see Ada drifting towards run-time /
>> dynamic-typing junk.
> 
> Runtime-typing and dynamic-typing are two different things, no?

Possibly, depends on how you define it. Anyway all boils down to run-time
checks (faults) vs. compile-time checks (errors/bugs). A failed run-time
check is a program state to anticipate. More such checks you do, more
states you have, more difficult it becomes to design tests covering these
states, or just to keep in mind that such states exist and are reachable.

I don't buy run-time checks unless *proven* that compile-time check would
be impossible to have. And this is not an optimization issue.

> Ada has always had run-time checking:

Sure.

[ It is trivial to put up an example where no compile-time check can exist,
e.g.

   function Puzzle return Positive is
   begin
      if HALT (p) then
         return -1;
      else
         return 1;
      end if;
   end Puzzle;

It is a halting problem to prove that Puzzle does not raise
Constraint_Error. ]

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



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

* Re: Is this expected behavior or not
  2013-03-22 14:54                                                                             ` Dmitry A. Kazakov
@ 2013-03-22 22:18                                                                               ` J-P. Rosen
  2013-03-22 23:05                                                                                 ` Shark8
  2013-03-23  8:14                                                                                 ` Dmitry A. Kazakov
  0 siblings, 2 replies; 242+ messages in thread
From: J-P. Rosen @ 2013-03-22 22:18 UTC (permalink / raw)


Le 22/03/2013 15:54, Dmitry A. Kazakov a �crit :
>> No, it is not the operation that gives different result, it's the
>> > assignment of a value that is incompatible with the variable's
>> > constraint that raises C_E.
> There is no assignment in my example. Assignment is in the *body* of the
> operation Foo.
No, assignment happens after returning from Foo.

[..]
> And what is so special about assignments?
Assignment is to a variable, and a variable has a subtype. It's the
checking of the constraint when assigning to a variable that raises C_E.

>> > The theory of ADT has no notion of subtypes (Ada definition).
> There is nothing special in Ada-subtypes. They are just ADTs.
You say they are. The rest of the world says they are not. We have come
to the point where nothing else can be added.

>> > Therefore,
>> > you can't translate Ada's subtypes into the terms of ADT.
> I just did it.
And that's where everybody (including those who designed/maintain the
language) thinks you are wrong.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-22 22:18                                                                               ` J-P. Rosen
@ 2013-03-22 23:05                                                                                 ` Shark8
  2013-03-23  8:32                                                                                   ` Dmitry A. Kazakov
  2013-03-23  8:14                                                                                 ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-22 23:05 UTC (permalink / raw)


On Friday, March 22, 2013 4:18:02 PM UTC-6, J-P. Rosen wrote:
> Le 22/03/2013 15:54, Dmitry A. Kazakov a �crit :
> 
> >> > Therefore,
> >> > you can't translate Ada's subtypes into the terms of ADT.
> > I just did it.
> 
> And that's where everybody (including those who designed/maintain the
> language) thinks you are wrong.

I think I can see Dmitry's point but, like you said earlier, it's a matter of definitions if you'll allow me a stab at Dmitry->everybody-else translation it's like this:

The notion of TYPE is two sets: {v | values of the type} & {o | operations on that type}

Given that a "subtype" may have different valid values 'v' than its parent type (e.g. Positive has restricted valid-values than Integer) then he wishes to call it a TYPE.

Everyone else is saying that Ada's notion of "subtype" contains a third set, a subset of of v {valid | the valid values}, and that v /= valid is not reason to panic and call "subtype" a true type simply because there are [possibly] values contained in its parent's v that are not present in the subtype's valid.

So the problem is in the conflation of "values" and "valid values" of some [sub]type.

----------------------------------------------------------------

That all is, IMO, a problem exacerbated in CS by the overpowering prevalence of "extension" in the "Object Oriented" paradigm; this even to the point that some of the new CS graduates [superficially] seem utterly unable to grasp the usefulness/utility of excluding values. {Though the attitude is surprising given the math/logic background/history of CS: where one routinely excludes things as a premise.} -- It's so odd that the idea of subtyping is so rare that it becomes difficult to explain the usefulness thereof to other programmers {like trying to explain that a "plow" is a good/useful thing to [other] farmers...} simply because the idea is so _obvious_.



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

* Re: Is this expected behavior or not
  2013-03-22 20:51                                                                         ` Dmitry A. Kazakov
@ 2013-03-22 23:34                                                                           ` Robert A Duff
  2013-03-23  8:41                                                                             ` Dmitry A. Kazakov
  2013-03-23  2:29                                                                           ` Nasser M. Abbasi
  1 sibling, 1 reply; 242+ messages in thread
From: Robert A Duff @ 2013-03-22 23:34 UTC (permalink / raw)


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

> [ It is trivial to put up an example where no compile-time check can exist,
> e.g.

I don't think so.  Compile-time checks just need to be more conservative
to avoid running afoul of the halting problem.

>    function Puzzle return Positive is
>    begin
>       if HALT (p) then
>          return -1;
>       else
>          return 1;
>       end if;
>    end Puzzle;

GNAT has a mode in which the above is a compile-time error.
Use the -gnatwae switch, and you are using an Ada-like language
in which the above is illegal.

It's similar to this Ada:

   procedure P is
      Const : constant Integer := 123;
   begin
      if HALT (p) then
         Const := 123; -- Illegal!
      end if;
   end Puzzle;

The compiler doesn't have to prove that the assignment statement
is reachable, nor that the assignment will actually change the
value of the constant.  It's illegal anyway.  The language designer
gets to choose between more-conservative compile time rules
versus more-liberal run-time checks.

> It is a halting problem to prove that Puzzle does not raise
> Constraint_Error. ]

True, but your first-quoted statement above does not follow from this.
In fact, it is trivial to design a language in which all
language-defined errors are detected at compile time.
(But it's somewhere between difficult and impossible to design
a *useful* language with that property.)

- Bob



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

* Re: Is this expected behavior or not
  2013-03-22 20:51                                                                         ` Dmitry A. Kazakov
  2013-03-22 23:34                                                                           ` Robert A Duff
@ 2013-03-23  2:29                                                                           ` Nasser M. Abbasi
  1 sibling, 0 replies; 242+ messages in thread
From: Nasser M. Abbasi @ 2013-03-23  2:29 UTC (permalink / raw)


On 3/22/2013 2:51 PM, Dmitry A. Kazakov wrote:

> Anyway all boils down to run-time
> checks (faults) vs. compile-time checks (errors/bugs). A failed run-time
> check is a program state to anticipate. More such checks you do, more
> states you have, more difficult it becomes to design tests covering these
> states, or just to keep in mind that such states exist and are reachable.
>
> I don't buy run-time checks unless *proven* that compile-time check would
> be impossible to have. And this is not an optimization issue.
>

In languages like Matlab and others like it, which do not
have static type checking and everything is done at run-time,
you'll typically see more than 50% of the code just doing
manual checks on function parameters to make sure it is the
'correct input' needed by the function.

Since there is no compiler to check statically, what ends
happening is that now the programmer is doing what the
compiler could have done and much better.

The programmer spends more time adding code to check that types
match (is this a structure? is this a string? is this a 1D vector
etc...) I am not even talking about checking that the
range of the values makes sense, just to check that the
input is even of the correct 'kind' that is all.

All of this is such a waste of time and energy, as a strongly
typed static language will not need all this, and one will
simply  declare variables of needed types and be done with
it and then spend the time thinking on the problem domain
itself and on the algorithm.

The sad thing, is that more and more languages are going to this
'write anything you want and leave the checking for when the code runs'
way of doing things.

--Nasser





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

* Re: Is this expected behavior or not
  2013-03-22 16:07                                                                     ` Dmitry A. Kazakov
  2013-03-22 20:10                                                                       ` Shark8
@ 2013-03-23  2:33                                                                       ` Randy Brukardt
  2013-03-23  4:44                                                                         ` Shark8
  2013-03-23  9:53                                                                         ` Dmitry A. Kazakov
  1 sibling, 2 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-03-23  2:33 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:2qwq2cdeuvhu$.qtnb8zyhuob9$.dlg@40tude.net...
> On Thu, 21 Mar 2013 18:27:22 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:i93qv6ba3bv0.wuicbsmfm5ha.dlg@40tude.net...
>>> On Wed, 20 Mar 2013 18:57:58 -0500, Randy Brukardt wrote:
>> ...
>>>> Even if you are willing to confuse users with implicit dispatching, 
>>>> you're
>>>> also talking about turning every slice reference into a loop.
>
>>> I don't see why. When the slice object happens to be class-wide, you 
>>> have
>>> a dope with a tag, bounds and a reference to some yet-to-be-discovered
>>> representation. When the slice is specific, you have a dope with bounds
>>> and a reference to some statically known representation.
>>
>> The underlying model of a slice is an implicit loop. We already have to 
>> use
>> loops to implement some slices in existing Ada; there is no possibility 
>> of
>> eliminating that. That's because ultimately everything is done on machine
>> objects (bytes, words, dwords, etc.) and you always need a loop if you 
>> are
>> going to operate on more than one.
>
> I still don't understand why is it relevant. Ada already has "loops" you
> are talking about for String and Wide_String. Why cannot you use them for
> their representations after selecting through dispatch?

You can - but there is no benefit to doing so, so why bother?

>> Because of that, there is almost no value to slicing operations unless 
>> you
>> know the representation and can use block move instructions.
>
> I want to be able to pass a slice to Put_Line without copying.

I want to win the Powerball so I can use the money to advance Ada and 
programming. Doesn't mean that it's practical or possible.

>> There's nothing that you can do with a slice that you can't do with a 
>> loop,
>> and usually the loop is easier to write and understand.
>
> Are you suggesting to call Put from a loop instead of Put_Line? I Don't
> want the language forcing me doing that.

You need a loop somewhere (or a complex abstraction); I suggest it be done 
at the call-site because there is insufficient value to doing it elsewhere. 
In your particular example, that means that the slice needs to be a new 
object. That doesn't necessarily mean copying of the data. If the designer 
of the abstraction, have put in enough smarts to share representations --  
after all, if Unbounded_String can do it, so can Unbounded_UTF8_String. But 
as with Unbounded_String, I don't think the language should get involved in 
this. A compiler can copy a slice of an String any time it wants in Ada 
today -- I see no reason to change that. (And Janus/Ada uses that to support 
generic sharing in some instances.)

...
>> Slicing is already impossible for the case that we're talking about,
>
> ?
>
> Normal strings have slices and should continue to have them.

Sure, but Root_String'Class is a separate type hierarchy. I don't think 
there can be any sharing between them other than through a set of defined 
conversions. If we go this way, new programs should avoid String and 
Wide_String altogether (there would be a new type rooted at Root_String that 
provided those representations).

>> and
>> interface to foreign language already has to be done through special 
>> types.
>
> Which should certainly be in the same class! There is no semantic reason
> why char_array should not be considered string.

It won't work, semantically or implementation-wise. This is a total restart 
of String semantics, and the old semantics will still exist (probably in 
Annex J). There is no way to make the existing array semantics work like a 
tagged type, and that is absolutely necessary for dispatching to work (even 
if it isn't a "tagged type" in Ada terms).

...
>> No I mean all objects. It should be none of your business how the 
>> compiler
>> implements objects
>
> On the contrary, the compiler is free to choose a representation under the
> constraints specified by the programmer. I don't want Ada to become C#.

That's the same thing I said, so I don't know why you are claiming that this 
is different. The compiler always has the power to reject things the 
programmer specifies if it can't implement them. (The "Recommended Level of 
Support" puts some minimum requires on what ought to be supported.)

...
>> None of the above makes any sense whatsoever. We need all of those things 
>> in
>> the object in order to generate code.
>
> So, you want to describe all possible problem domains in the RM? The RM
> should know that a matrix of 2 rows and 5 columns can be multiplied to a
> 5x8 matrix, but not to a 8x8 matrix? Good luck with that!

No, but we need the building blocks so that one can specify such things as 
part of the language.

>> I suspect that if your model became the law of the land, compilers would
>> generate very bad code for any cases like the ones you want, and you
>> wouldn't be able to use the result anyway.
>
> Nobody tried. But I doubt it. My proposals have a goal to significantly
> simplify the language. Ada 2005 and 2012 added a huge number of special
> cases requiring special treatment. That surely complicates optimization of
> Ada programs which is already not great. Smaller and more regular language
> would be easier to optimize.

The definition of the language doesn't have much effect on the ability to 
optimize (almost everything that does is in the infamous 11.6). Optimization 
is almost completely done on language-independent intermediate codes, so the 
language definition only comes into play if some normal optimization has to 
be blocked (there are a few cases of this in Ada). A simpler definition 
*might* be easier to interpret and convert to that intermediate code, but it 
is just as likely that it would have to be completely implemented by 
run-time structures (like type tags) that defy optimization.

...
> This is a totally bogus argument. OO imposes no overhead on specific 
> types.

That's kool-aid invented by the Ada 9x team. It's not remotely true, 
especially as all usable OOP types have to be controlled.

...
> Nobody proposes to change tagged types. The idea is to add classes to
> non-tagged types by adding tag to the class-wide object while keeping
> specific objects as-is.

But there is no point in doing so. Inheritance of operations of discrete 
types is a bad idea that Ada already has and is virtually useless. Why go 
further down a path to nowhere?
...
>>> Container libraries need to be implemented as well. I don't want to 
>>> expose
>>> access type, I want referential semantics.
>>
>> And that's the point of 4.1.5. The only thing you can't do is write "new"
>
> (what about 'Access? What about Unchecked_Deallocation?)

Huh? Unchecked_Deallocation is a procedure, and you surely can write a 
procedure. Since you can't use new, there is no point in using the 
predefined unchecked_deallocation anyway (it only works on objects allocated 
by new). If you really need these things, use storage pools and don't even 
think about changing the access values.

I don't see any way to use 'Access with a safe abstraction; it's always 
illegal so you have to use 'Unchecked_Access and create dangling pointers.

>> that way, but calling a function to do that doesn't seem that bad.
>
> How do I put such a reference in an array, for example? 4.1.5 would be
> extremely difficult to use for intended purpose.

It's just a tagged object, do with it what you want. I don't see why you 
think there is a problem.


...
>> Ahh, but that was a case where the "existing semantics" was good enough 
>> so
>> we didn't create a new thing. This is a very special access type, one 
>> that
>> almost never can be copied -- for practical purposes it can only be
>> dereferenced. That's what we needed. Note that there is no intent that
>> anyone ever create an object for this access type (and that is where all 
>> of
>> the problems lie). It just has the syntax of an access type so we didn't
>> have to invent a new thing to get dereferencing.
>
> You have a very specific use case in mind, namely containers. There is a
> whole world outside that, for which what you said is untrue, e.g. for 
> smart
> pointers. The thing not only exposes access, it also exposes the target
> type.

You have to expose the target type in order to have strong typing. How could 
you hide it and still make type checks?

> For smart pointers and handles you might what to hide both. Consider
> a handle to a file. You certainly don't want to make File_Descriptor it
> points to, visible. You want the handle to implement file I/O interface
> routed privately to the descriptor. You also want handles be copyiable and
> comparable, but treated as references to some opaque limited object.

I don't see the problem -- here the target type would be private (that Ada's 
for "opaque", of course). And in all honesty, if you want an opaque handle, 
I don't see any reason that you would want to do a visible dereference of 
it. The ONLY reason that we need 4.1.5 is so that we can assign directly 
into the target type. For all other purposes, accessor functions work just 
as well, so you would be better off using them in such cases.

Needing to write into parts of objects accessed by handles is a 
container-like problem. In other cases, using regular Ada 95-style code 
works just fine (as we did in the Ada 2005 version of the containers 
library).

...
>>> Even if it were compile-time it would require same representation for 
>>> all
>>> involved objects. How would I do it for Unsigned_1 and String?
>>
>> I don't see this necessarily. You certainly can use dispatching to 
>> support
>> different representations.
>
> No way. Consider operation Send:
>
>   procedure Send (To : in out Register; Value : Unsigned_1);
>
>   procedure Send (To : in out Register; Value : String);
>
> It cannot dispatch! Firstly, Unsigned_1 and String are not in the same
> class. Secondly, even if they were, it would be MD! So, you need MI and MD
> to make it happen. Without them, poor man's solution is messing with
> generics.

If you really wanted to go this way, you'd put all of those types in the 
same class. (Having every possible advantage without any disadvantages is 
impossible.) You are right about multiple dispatch in some cases, although 
it's usually possible to layer those:

    procedure Send (To : in out Register; Value : Data'Class);

which is legal Ada. You then have to dispatch to somehow marshall the values 
(streams would work in this case, although you'd probably want to have a 
private version for your own use).

I admit I don't see any point to a tagged Register type, but I take your 
word for it that there is some value to that.

...
>> I think
>> these need a balance, especially as modern static analyzers can remove 
>> the
>> vast majority of them (or warn that they might fail, which is a cause for
>> concern).
>
> It is not about removing checks, though performance is a concern too. The
> major problem is that failed checks must be flagged as errors. You are a
> compiler writer, I am designing automation systems. To me run-time check 
> is
> much too late. A fault can break real things, apart from maintenance.
> Imagine Claw running on an oil platform. Do you own a helicopter?

That's my point about static analysis. Such a tool should be able to prove 
that the majority of run-time checks can't happen, and give you a list of 
those remaining. (That's assuming appropriate declarations and assertions, 
of course). The only ones that you have to worry about are those that can't 
be proved.

Of course, that depends on the underlying platform. If Claw is running on an 
oil platform, you've got problems because that's running on top of Windows. 
And we can't guess why or when Windows will fail something. So pretty much 
everything comes down to run-time checks.

You can mitigate problems with run-time checks with last-chance error 
handlers and the like. But I'd prefer to prove they don't happen -- without 
constraining the language and programs to the point where you can't write 
anything realistic (the SPARK problem). That appears like more run-time 
checks (in terms of how you write the code), but the ultimate result is just 
as safe (and much less complicated, so it's a lot more likely to be right --  
I'd never trust any program with more than a handful of generics, it's just 
too hard to get the compilers to handle those right).

                                          Randy.





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

* Re: Is this expected behavior or not
  2013-03-23  2:33                                                                       ` Randy Brukardt
@ 2013-03-23  4:44                                                                         ` Shark8
  2013-03-25 22:24                                                                           ` Randy Brukardt
  2013-03-23  9:53                                                                         ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-23  4:44 UTC (permalink / raw)


On Friday, March 22, 2013 8:33:02 PM UTC-6, Randy Brukardt wrote:
> 
> I'd never trust any program with more than a handful of generics, it's just 
> too hard to get the compilers to handle those right).

That seems a bit odd... I would think that once you had a generic* method for handling overloading you could apply that to generics as well.

[* Pun intended.]



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

* Re: Is this expected behavior or not
  2013-03-22 22:18                                                                               ` J-P. Rosen
  2013-03-22 23:05                                                                                 ` Shark8
@ 2013-03-23  8:14                                                                                 ` Dmitry A. Kazakov
  2013-03-23  9:02                                                                                   ` J-P. Rosen
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-23  8:14 UTC (permalink / raw)


On Fri, 22 Mar 2013 23:18:02 +0100, J-P. Rosen wrote:

> Le 22/03/2013 15:54, Dmitry A. Kazakov a �crit :
>>> No, it is not the operation that gives different result, it's the
>>> > assignment of a value that is incompatible with the variable's
>>> > constraint that raises C_E.
>> There is no assignment in my example. Assignment is in the *body* of the
>> operation Foo.
> No, assignment happens after returning from Foo.

You mean "assignment operation," rather than "assignment statement"?

Fine, that won't safe you either. Replace "the operation Foo of Positive,"
with "the assignment operation of Positive." You still have different
behavior of an operation. I used Foo merely to prevent yet another fume
about whether assignment is an operation. If it is, then simply consider:

   declare
       X : Positive;
   begin
       X := -1; -- With Integer it behaves *differently*
   end;

So, WHERE is the difference, what make the program above to work
differently, if everything [value, type, operation] is SAME? 

>>> > The theory of ADT has no notion of subtypes (Ada definition).
>> There is nothing special in Ada-subtypes. They are just ADTs.

> You say they are. The rest of the world says they are not.

Georg and Randy seem to dismiss ADT altogether.

> We have come
> to the point where nothing else can be added.

You could add, if you are not with Georg and Randy, why you think Positive
is not an ADT.

>>> > Therefore,
>>> > you can't translate Ada's subtypes into the terms of ADT.
>> I just did it.
> And that's where everybody (including those who designed/maintain the
> language) thinks you are wrong.

But none said why. They should have indicated some flaws in the mapping
Positive ~ ADT. So far the only argument was that ADT is useless. May be,
but irrelevant, because it tells nothing about why Positive is not an ADT.

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



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

* Re: Is this expected behavior or not
  2013-03-22 23:05                                                                                 ` Shark8
@ 2013-03-23  8:32                                                                                   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-23  8:32 UTC (permalink / raw)


On Fri, 22 Mar 2013 16:05:47 -0700 (PDT), Shark8 wrote:

> On Friday, March 22, 2013 4:18:02 PM UTC-6, J-P. Rosen wrote:
>> Le 22/03/2013 15:54, Dmitry A. Kazakov a �crit :
>> 
>>>> > Therefore,
>>>> > you can't translate Ada's subtypes into the terms of ADT.
>>> I just did it.
>> 
>> And that's where everybody (including those who designed/maintain the
>> language) thinks you are wrong.
> 
> I think I can see Dmitry's point but, like you said earlier, it's a matter
> of definitions

Then there should an alternative definition of ADT...

> So the problem is in the conflation of "values" and "valid values" of some [sub]type.

The problem is that subset is a set. So valid values are simply values of
Positive.

If you don't change the definition of ADT, Positive will keep on being ADT.

> That all is, IMO, a problem exacerbated in CS by the overpowering
> prevalence of "extension" in the "Object Oriented" paradigm; this even to
> the point that some of the new CS graduates [superficially] seem utterly
> unable to grasp the usefulness/utility of excluding values.

Right. The litmus test is to ask somebody who does not know Ada, isn't C's
int a class (type). This would produce no less fume as Positive vs. ADT.

It is a pity that Ada community keeps on insisting on this on their side of
the wall, refusing to see that either subtype or tagged type, they are just
different ways of creating a new type from existing ones, while having a
type for objects accommodating values of both ancestor and predecessor
types.

There is no reason why derived types shall always be extensions. It is an
*implementation* detail. Ada people should knew better about separation of
interface and implementation.

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



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

* Re: Is this expected behavior or not
  2013-03-22 23:34                                                                           ` Robert A Duff
@ 2013-03-23  8:41                                                                             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-23  8:41 UTC (permalink / raw)


On Fri, 22 Mar 2013 19:34:09 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> [ It is trivial to put up an example where no compile-time check can exist,
>> e.g.
> 
> I don't think so.  Compile-time checks just need to be more conservative
> to avoid running afoul of the halting problem.

OK, for any written program, there is no halting problem, as you can always
enumerate all states of any finite program using brute force.

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



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

* Re: Is this expected behavior or not
  2013-03-23  8:14                                                                                 ` Dmitry A. Kazakov
@ 2013-03-23  9:02                                                                                   ` J-P. Rosen
  2013-03-23 10:19                                                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-03-23  9:02 UTC (permalink / raw)


Le 23/03/2013 09:14, Dmitry A. Kazakov a �crit :
>    declare
>        X : Positive;
>    begin
>        X := -1; -- With Integer it behaves *differently*
>    end;
> 
> So, WHERE is the difference, what make the program above to work
> differently, if everything [value, type, operation] is SAME? 
The values are the same, the subtype is a property of a variable.

The assignment behaves the same: check that the value belongs to the
allowed values for the variable, and raise C_E if not. The check
succeeds for some variables, and fails for others. This does not mean it
is a different operation.

Once again: a subtype is just an extra check added in some contexts to
some objects. It does not define a new set of values, i.e. the "1" for
Positive is the same as the "1" for Integer (while it is different from
the "1" of some user defined type).
-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-23  2:33                                                                       ` Randy Brukardt
  2013-03-23  4:44                                                                         ` Shark8
@ 2013-03-23  9:53                                                                         ` Dmitry A. Kazakov
  2013-03-25 22:58                                                                           ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-23  9:53 UTC (permalink / raw)


On Fri, 22 Mar 2013 21:33:02 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:2qwq2cdeuvhu$.qtnb8zyhuob9$.dlg@40tude.net...

>> I still don't understand why is it relevant. Ada already has "loops" you
>> are talking about for String and Wide_String. Why cannot you use them for
>> their representations after selecting through dispatch?
> 
> You can - but there is no benefit to doing so, so why bother?

Egh, we wanted a class of strings, didn't we?

>>> There's nothing that you can do with a slice that you can't do with a 
>>> loop, and usually the loop is easier to write and understand.
>>
>> Are you suggesting to call Put from a loop instead of Put_Line? I Don't
>> want the language forcing me doing that.
> 
> You need a loop somewhere (or a complex abstraction);

Yes, the loop shall be within Put_Line.

> In your particular example, that means that the slice needs to be a new 
> object.

It certainly is, already.

> That doesn't necessarily mean copying of the data. If the designer 
> of the abstraction, have put in enough smarts to share representations --  
> after all,

You should break your mental block. No shared representation, I want
different representations for different string types.

>>> Slicing is already impossible for the case that we're talking about,
>>
>> ?
>>
>> Normal strings have slices and should continue to have them.
> 
> Sure, but Root_String'Class is a separate type hierarchy.

I see, yet another outhouse, also. Ada quickly becomes a shantytown...

>>> and
>>> interface to foreign language already has to be done through special 
>>> types.
>>
>> Which should certainly be in the same class! There is no semantic reason
>> why char_array should not be considered string.
> 
> It won't work, semantically or implementation-wise. This is a total restart 
> of String semantics, and the old semantics will still exist (probably in 
> Annex J). There is no way to make the existing array semantics work like a 
> tagged type, and that is absolutely necessary for dispatching to work (even 
> if it isn't a "tagged type" in Ada terms).

The way is to allow untagged T to have T'Class. This will preserve all
semantics and all existing representations. Not even an explicit root type
is needed, e.g. for char_array. The technique makes it possible to have
ad-hoc supertypes, which would serve the purpose, e.g. you would define
Put_Line on such a supertype and it will work for both String and
char_array. Not a line changed in Standard or Interfaces.C.

>>> No I mean all objects. It should be none of your business how the 
>>> compiler implements objects
>>
>> On the contrary, the compiler is free to choose a representation under the
>> constraints specified by the programmer. I don't want Ada to become C#.
> 
> That's the same thing I said, so I don't know why you are claiming that this 
> is different.

It is different becauseto me it should be up to the programmer to set these
constraints. The constraint is that char_array is a sequence of aliased
char without gaps. If the compiler does not know how to implement a
particular string operation on char_array, it should ask me.

>>> None of the above makes any sense whatsoever. We need all of those things 
>>> in the object in order to generate code.
>>
>> So, you want to describe all possible problem domains in the RM? The RM
>> should know that a matrix of 2 rows and 5 columns can be multiplied to a
>> 5x8 matrix, but not to a 8x8 matrix? Good luck with that!
> 
> No, but we need the building blocks so that one can specify such things as 
> part of the language.

And the building block necessary is a statically checked constraint. The
check shall be user-defined. The constraint shall be not present in
constrained objects. This building block would give everything needed to
have string class as well.

>> This is a totally bogus argument. OO imposes no overhead on specific 
>> types.
> 
> That's kool-aid invented by the Ada 9x team. It's not remotely true, 
> especially as all usable OOP types have to be controlled.

See above. T'Class for all types!

>> Nobody proposes to change tagged types. The idea is to add classes to
>> non-tagged types by adding tag to the class-wide object while keeping
>> specific objects as-is.
> 
> But there is no point in doing so. Inheritance of operations of discrete 
> types is a bad idea that Ada already has and is virtually useless.

?

> Why go further down a path to nowhere?

Not even single step made so far. I see a lot of ad-hocks added recently
which directly influence discrete types. All these aspects, attributes
('Read) are defined on discrete types as well. You are dragged down the
path, looking backwards...

>> How do I put such a reference in an array, for example? 4.1.5 would be
>> extremely difficult to use for intended purpose.
> 
> It's just a tagged object, do with it what you want. I don't see why you 
> think there is a problem.

We will see. My prediction is that 4.1.5 will be very rarely used. Those
who will try it, will have to fight with language limitations imposed by
the design and then will drop it. Libraries based on it, will in turn
become difficult to use for average programmers. Too much mental overhead,
too many helper types (a bad OO-fest), too much time to find the package
where the mess resides, too much efforts to understand why the compiler
rejected obvious code...

>>> Ahh, but that was a case where the "existing semantics" was good enough 
>>> so we didn't create a new thing. This is a very special access type, one 
>>> that almost never can be copied -- for practical purposes it can only be
>>> dereferenced. That's what we needed. Note that there is no intent that
>>> anyone ever create an object for this access type (and that is where all 
>>> of the problems lie). It just has the syntax of an access type so we didn't
>>> have to invent a new thing to get dereferencing.
>>
>> You have a very specific use case in mind, namely containers. There is a
>> whole world outside that, for which what you said is untrue, e.g. for 
>> smart pointers. The thing not only exposes access, it also exposes the target
>> type.
> 
> You have to expose the target type in order to have strong typing. How could 
> you hide it and still make type checks?

Why should target type be public?

> The ONLY reason that we need 4.1.5 is so that we can assign directly 
> into the target type.

Yes, it is a hack designed for single use case.

>>>> Even if it were compile-time it would require same representation for all
>>>> involved objects. How would I do it for Unsigned_1 and String?
>>>
>>> I don't see this necessarily. You certainly can use dispatching to 
>>> support different representations.
>>
>> No way. Consider operation Send:
>>
>>   procedure Send (To : in out Register; Value : Unsigned_1);
>>
>>   procedure Send (To : in out Register; Value : String);
>>
>> It cannot dispatch! Firstly, Unsigned_1 and String are not in the same
>> class. Secondly, even if they were, it would be MD! So, you need MI and MD
>> to make it happen. Without them, poor man's solution is messing with
>> generics.
> 
> If you really wanted to go this way, you'd put all of those types in the 
> same class. (Having every possible advantage without any disadvantages is 
> impossible.) You are right about multiple dispatch in some cases, although 
> it's usually possible to layer those:
> 
>     procedure Send (To : in out Register; Value : Data'Class);
> 
> which is legal Ada.

Sure, this is exactly how I do it. It bursts into dozens of generic
packages and hundreds of their instances. Unless you propose to code all
hundreds of combinations manually... How should I test THIS?

> I admit I don't see any point to a tagged Register type, but I take your 
> word for it that there is some value to that.

Register must be tagged because Send is an operation on the register [and
ultimately on the device the register refers to]
 
>>> I think
>>> these need a balance, especially as modern static analyzers can remove 
>>> the
>>> vast majority of them (or warn that they might fail, which is a cause for
>>> concern).
>>
>> It is not about removing checks, though performance is a concern too. The
>> major problem is that failed checks must be flagged as errors. You are a
>> compiler writer, I am designing automation systems. To me run-time check 
>> is much too late. A fault can break real things, apart from maintenance.
>> Imagine Claw running on an oil platform. Do you own a helicopter?
> 
> That's my point about static analysis. Such a tool should be able to prove 
> that the majority of run-time checks can't happen, and give you a list of 
> those remaining.

I don't need any list. Should I send it to my customers? I need the program
fail to compile when writing analogue input.

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



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

* Re: Is this expected behavior or not
  2013-03-23  9:02                                                                                   ` J-P. Rosen
@ 2013-03-23 10:19                                                                                     ` Dmitry A. Kazakov
  2013-03-23 21:53                                                                                       ` J-P. Rosen
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-23 10:19 UTC (permalink / raw)


On Sat, 23 Mar 2013 10:02:11 +0100, J-P. Rosen wrote:

> Le 23/03/2013 09:14, Dmitry A. Kazakov a �crit :
>>    declare
>>        X : Positive;
>>    begin
>>        X := -1; -- With Integer it behaves *differently*
>>    end;
>> 
>> So, WHERE is the difference, what make the program above to work
>> differently, if everything [value, type, operation] is SAME? 

> The values are the same, the subtype is a property of a variable.

And an operation should *know* the properties of involved operands beyond
values and types. Right?

> The assignment behaves the same: check that the value belongs to the
> allowed values for the variable, and raise C_E if not.

Of course it is the same assignment, according to you. Why the effect is
different?

> The check
> succeeds for some variables, and fails for others. This does not mean it
> is a different operation.

But the ultimate effect of the operation is different when check fails.

> Once again: a subtype is just an extra check added in some contexts to
> some objects. It does not define a new set of values, i.e. the "1" for
> Positive is the same as the "1" for Integer (while it is different from
> the "1" of some user defined type).

And 0xFF is same for signed and unsigned char. This is why C is called
weakly typed. It is no matter how do you call what is going on. Only the
effect matters. The effect is that the behavior changes.

Check is needed to be put somewhere. Programmers design programs in terms
of values, operations and types. You can consider check an operation or a
part of. You can consider check a part of the type which magically changes
the behavior of operations defined on the type.

In any case, it will have the effect of making some aspect of Positive
different from Integer. Which makes it a different type. And this is
clearly the intent of the programmer using Positive. Because otherwise he
would use Integer.

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



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

* Re: Is this expected behavior or not
  2013-03-23 10:19                                                                                     ` Dmitry A. Kazakov
@ 2013-03-23 21:53                                                                                       ` J-P. Rosen
  2013-03-24  8:17                                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-03-23 21:53 UTC (permalink / raw)


Le 23/03/2013 11:19, Dmitry A. Kazakov a �crit :
> Of course it is the same assignment, according to you. Why the effect is
> different?
Because it operates on different variables. Any subprogram that contains
an "if" behaves differently depending on the parameters. It does not
mean that each possible value of the parameters inherits a different
subprogram.

>> Once again: a subtype is just an extra check added in some contexts to
>> some objects. It does not define a new set of values, i.e. the "1" for
>> Positive is the same as the "1" for Integer (while it is different from
>> the "1" of some user defined type).
> 
> And 0xFF is same for signed and unsigned char. This is why C is called
> weakly typed. It is no matter how do you call what is going on. Only the
> effect matters. The effect is that the behavior changes.
In C yes, there is only one integer type. Not in Ada. What's your point?


-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-23 21:53                                                                                       ` J-P. Rosen
@ 2013-03-24  8:17                                                                                         ` Dmitry A. Kazakov
  2013-03-24  8:27                                                                                           ` J-P. Rosen
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-24  8:17 UTC (permalink / raw)


On Sat, 23 Mar 2013 22:53:15 +0100, J-P. Rosen wrote:

> Le 23/03/2013 11:19, Dmitry A. Kazakov a �crit :
>> Of course it is the same assignment, according to you. Why the effect is
>> different?

> Because it operates on different variables.

How are they different? They have same name and same type (according to
you) etc.

Moreover, you want to tell that the behavior of an operation would depend
on a variable? Do I read it right? Not on the type or value it has. This is
how you want to deal with simple scalar types?

> Any subprogram that contains
> an "if" behaves differently depending on the parameters.

There is no if's in the program. The program applies an operation to a
variable. Nothing more.

>>> Once again: a subtype is just an extra check added in some contexts to
>>> some objects. It does not define a new set of values, i.e. the "1" for
>>> Positive is the same as the "1" for Integer (while it is different from
>>> the "1" of some user defined type).
>> 
>> And 0xFF is same for signed and unsigned char. This is why C is called
>> weakly typed. It is no matter how do you call what is going on. Only the
>> effect matters. The effect is that the behavior changes.

> In C yes, there is only one integer type. Not in Ada.

Only one type for Integer and Positive, just as you said.

> What's your point?

Your interpretation of Ada subtypes is untyped.

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



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

* Re: Is this expected behavior or not
  2013-03-24  8:17                                                                                         ` Dmitry A. Kazakov
@ 2013-03-24  8:27                                                                                           ` J-P. Rosen
  2013-03-24 13:01                                                                                             ` AdaMagica
  2013-03-25  8:32                                                                                             ` Dmitry A. Kazakov
  0 siblings, 2 replies; 242+ messages in thread
From: J-P. Rosen @ 2013-03-24  8:27 UTC (permalink / raw)


Le 24/03/2013 09:17, Dmitry A. Kazakov a �crit :
> Moreover, you want to tell that the behavior of an operation would depend
> on a variable? Do I read it right? Not on the type or value it has. This is
> how you want to deal with simple scalar types?
Yes, the behaviour of assignment depends on the SUBTYPE of the target
variable.

>> Any subprogram that contains
>> an "if" behaves differently depending on the parameters.
> 
> There is no if's in the program. The program applies an operation to a
> variable. Nothing more.
There is a check => an implicit if

> Your interpretation of Ada subtypes is untyped.
> 
You are doing interpretations. I am reading the ARM

Now, I think we have reached a point where nothing new can be added, and
we are boring people. Let's agree that we don't agree and stop the thread.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-03-24  8:27                                                                                           ` J-P. Rosen
@ 2013-03-24 13:01                                                                                             ` AdaMagica
  2013-03-25  8:32                                                                                             ` Dmitry A. Kazakov
  1 sibling, 0 replies; 242+ messages in thread
From: AdaMagica @ 2013-03-24 13:01 UTC (permalink / raw)


It's amazing how patient Randy and Jean-Pierre are with this paranoic discussion turning round in circles and never reaching an end because Dmitry always turns their words in their mouths.



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

* Re: Is this expected behavior or not
  2013-03-24  8:27                                                                                           ` J-P. Rosen
  2013-03-24 13:01                                                                                             ` AdaMagica
@ 2013-03-25  8:32                                                                                             ` Dmitry A. Kazakov
  2013-03-25  9:19                                                                                               ` Georg Bauhaus
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-25  8:32 UTC (permalink / raw)


On Sun, 24 Mar 2013 09:27:02 +0100, J-P. Rosen wrote:

> Le 24/03/2013 09:17, Dmitry A. Kazakov a �crit :
>> Moreover, you want to tell that the behavior of an operation would depend
>> on a variable? Do I read it right? Not on the type or value it has. This is
>> how you want to deal with simple scalar types?
> Yes, the behaviour of assignment depends on the SUBTYPE of the target
> variable.

Merely in order to warn other readers of c.l.a. It is not a variable
property and there exist cases when this matters. E.g.

   X : Integer := Positive'(-1);

This must raise Constrant_Error, though X as an Integer variable does not
have any constraint; though Positive allegedly has the value -1. But
qualified expression disagrees.

Another example where it does matter, that the constraint is not a property
of the variable, is the behavior of X'Valid. We can trick the compiler to
assign -1 to a Positive through the hole in the semantics of renaming and
this will become a "valid" value of:

   with Ada.Text_IO; use Ada.Text_IO;
   procedure Test is
      X : Integer;
      Y : Positive renames X;
   begin
      Y := -1;
      Put_Line (Boolean'Image (Y'Valid));
   end Test;

TRUE is printed.

[I don't know if Ada 2012 is going to fix this, e.g. considering range a
"predicate"]

> Now, I think we have reached a point where nothing new can be added, and
> we are boring people. Let's agree that we don't agree and stop the thread.

Yes.

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



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

* Re: Is this expected behavior or not
  2013-03-25  8:32                                                                                             ` Dmitry A. Kazakov
@ 2013-03-25  9:19                                                                                               ` Georg Bauhaus
  2013-03-25 10:08                                                                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-03-25  9:19 UTC (permalink / raw)


On 25.03.13 09:32, Dmitry A. Kazakov wrote:
> On Sun, 24 Mar 2013 09:27:02 +0100, J-P. Rosen wrote:
>
>> Le 24/03/2013 09:17, Dmitry A. Kazakov a �crit :
>>> Moreover, you want to tell that the behavior of an operation would depend
>>> on a variable? Do I read it right? Not on the type or value it has. This is
>>> how you want to deal with simple scalar types?
>> Yes, the behaviour of assignment depends on the SUBTYPE of the target
>> variable.
>
> Merely in order to warn other readers of c.l.a. It is not a variable
> property and there exist cases when this matters. E.g.
>
>     X : Integer := Positive'(-1);
>
> This must raise Constrant_Error,

Yes.

> though X as an Integer variable does not
> have any constraint;

Two things seem logically wrong, here, I think.

1. Ada's Standard.Integer has a constraint. Standard.Positive has
a constraint that is different from Standard.Integer's constraint.
Both, Integer and Positive, refer to the same Ada type, in Ada.

2. And no. Changing the situation by introducing qualified expression
and representing J-P. Rosen's comment as if being about that
situation (when it is not) does not kill the fact that, in Ada,
a constraint error like the above one is not a type error.

This has a type error, in Ada:

   X : Duration := Positive'(-1);

So has this

   X : Duration := Positive'(1);

If Constraint_Error is too weak for you, go ahead, rewrite the language,
and really do so:

If you want Positive to be a type, in Ada, and if it is easy to make it
a type, in Ada---like you have outlined in just a few sentences,
recently---do take the time to make the trivial adjustments to RM 3 etc,
all paragraphs, add or remove paragraphs as needed, outline efforts
needed for implementing, as you have done, and submit.




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

* Re: Is this expected behavior or not
  2013-03-25  9:19                                                                                               ` Georg Bauhaus
@ 2013-03-25 10:08                                                                                                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-25 10:08 UTC (permalink / raw)


On Mon, 25 Mar 2013 10:19:05 +0100, Georg Bauhaus wrote:

> If Constraint_Error is too weak for you, go ahead, rewrite the language,

?

I just give Ada-subtypes a well-typed interpretation, for those who enjoy
to think about it in terms of strong typing. Others are free to use other
interpretations [consistent with the language semantics]. They may have
difficulties with that, but this is not my concern.

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



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

* Re: Is this expected behavior or not
  2013-03-23  4:44                                                                         ` Shark8
@ 2013-03-25 22:24                                                                           ` Randy Brukardt
  2013-03-26  1:15                                                                             ` Shark8
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-25 22:24 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:c231e327-0859-4430-adfc-ed4de4de2208@googlegroups.com...
> On Friday, March 22, 2013 8:33:02 PM UTC-6, Randy Brukardt wrote:
>>
>> I'd never trust any program with more than a handful of generics, it's 
>> just
>> too hard to get the compilers to handle those right).
>
> That seems a bit odd... I would think that once you had a generic* method 
> for handling overloading you could apply that to generics as well.
>
> [* Pun intended.]

It's the combination of a wealth of things, overloading is the easy one. 
Certainly a shared implementation (like the one in Janus/Ada) makes 
everything harder, but there are enough oddities in the handling of formals 
that it won't ever be easy. It's really the result of having a strong 
contract model for generics; that prevents using simple textual substitution 
for thing. Of course, you need a strong contract model if you want the 
generic to be correct without knowing anything about the instantiations. 
(Same as you do for subprograms.)

                                  Randy.


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

* Re: Is this expected behavior or not
  2013-03-23  9:53                                                                         ` Dmitry A. Kazakov
@ 2013-03-25 22:58                                                                           ` Randy Brukardt
  2013-03-26 10:52                                                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-25 22:58 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:a96esjwiniqy$.op3wh7x9wrsl.dlg@40tude.net...
> On Fri, 22 Mar 2013 21:33:02 -0500, Randy Brukardt wrote:
...
>> That doesn't necessarily mean copying of the data. If the designer
>> of the abstraction, have put in enough smarts to share representations --
>> after all,
>
> You should break your mental block. No shared representation, I want
> different representations for different string types.

I was talking about sharing representations of *different* objects of the 
same string type (for instance, a string variable and a slice of that 
variable - that case, sharing the data might be preferred to copying it). 
Not talking about different types here; of course, the whole point of 
changing anything here is to allow different representations of the data.

>>>> Slicing is already impossible for the case that we're talking about,
>>>
>>> ?
>>>
>>> Normal strings have slices and should continue to have them.
>>
>> Sure, but Root_String'Class is a separate type hierarchy.
>
> I see, yet another outhouse, also. Ada quickly becomes a shantytown...

Unifying old junk it's possible without serious breakage of existing code, 
which is intolerable. It's better to start over and obsolete the old stuff.


>>>> and
>>>> interface to foreign language already has to be done through special
>>>> types.
>>>
>>> Which should certainly be in the same class! There is no semantic reason
>>> why char_array should not be considered string.
>>
>> It won't work, semantically or implementation-wise. This is a total 
>> restart
>> of String semantics, and the old semantics will still exist (probably in
>> Annex J). There is no way to make the existing array semantics work like 
>> a
>> tagged type, and that is absolutely necessary for dispatching to work 
>> (even
>> if it isn't a "tagged type" in Ada terms).
>
> The way is to allow untagged T to have T'Class. This will preserve all
> semantics and all existing representations. Not even an explicit root type
> is needed, e.g. for char_array. The technique makes it possible to have
> ad-hoc supertypes, which would serve the purpose, e.g. you would define
> Put_Line on such a supertype and it will work for both String and
> char_array. Not a line changed in Standard or Interfaces.C.

Sounds great, but it won't work in practice. You'd introduce a lot of 
ambiguities and break existing code that way. (That's why 
Ada.Strings.Unbounded_String doesn't have string literals; we couldn't find 
any way to add them without making most existing code using the package 
ambiguous.)

Secondly, the inheritance and overriding of untagged types is much looser 
than the that of tagged types; you don't even have to use the same parameter 
modes. That's not going to be compatible with dispatching, so you would have 
to make quite a bit of existing types illegal if you want to truly support 
Untagged'Class. (We had to introduce such an incompatibility when we "fixed" 
equality for untagged record types, and it was very controversal. I doubt 
that we would risk going further.)

I'm also dubious that good code can be generated for such a model, but 
that's a secondary concern vs. the incompatibility.

...
...
>>> This is a totally bogus argument. OO imposes no overhead on specific
>>> types.
>>
>> That's kool-aid invented by the Ada 9x team. It's not remotely true,
>> especially as all usable OOP types have to be controlled.
>
> See above. T'Class for all types!

See above -- this model is likely impossible for Ada. (It might work fine in 
a new language, but that's irrelevant here.)

...
>> Why go further down a path to nowhere?
>
> Not even single step made so far. I see a lot of ad-hocks added recently
> which directly influence discrete types. All these aspects, attributes
> ('Read) are defined on discrete types as well. You are dragged down the
> path, looking backwards...

No choice. We can *add* new stuff, but changes to old stuff isn't possible. 
And dispatching is incompatible with untagged types, simply because Ada 83 
got inheritance horribly wrong, and we're stuck with that.


>>> How do I put such a reference in an array, for example? 4.1.5 would be
>>> extremely difficult to use for intended purpose.
>>
>> It's just a tagged object, do with it what you want. I don't see why you
>> think there is a problem.
>
> We will see. My prediction is that 4.1.5 will be very rarely used. Those
> who will try it, will have to fight with language limitations imposed by
> the design and then will drop it. Libraries based on it, will in turn
> become difficult to use for average programmers. Too much mental overhead,
> too many helper types (a bad OO-fest), too much time to find the package
> where the mess resides, too much efforts to understand why the compiler
> rejected obvious code...

Like generics, the expectation is that hardly anyone will need to understand 
how it works. Just use it and get the expected semantics. And the compiler 
shouldn't be rejecting any obvious code unless the definition is screwed up. 
(That's the fault of the guru who set it up, not the user.)

There are large parts of Ada that aren't really expected to be used by "mere 
mortals". Generics, storage pools, generalized references and indexes, 
iterators, etc. In all of these cases, they really exist to make library 
packages easier to use; most users will use these things without worrying 
too much about how they're implemented.

I originally had a different model for 4.1.5 (most custom rules), but we 
determined that most of rules we needed already existed in the language. So 
it ended up a bit more complex (using a discriminant) in order to have far 
fewer new rules. That's usually a preferred trade-off.

...
>>> You have a very specific use case in mind, namely containers. There is a
>>> whole world outside that, for which what you said is untrue, e.g. for
>>> smart pointers. The thing not only exposes access, it also exposes the 
>>> target
>>> type.
>>
>> You have to expose the target type in order to have strong typing. How 
>> could
>> you hide it and still make type checks?
>
> Why should target type be public?

How do you enforce strong typing without that being the case? If you don't 
know what the target is, how do you determine how the resulting object can 
be used? (The type being public doesn't mean that the *contents* of the type 
are public -- of course the target could be an Ada private type.) The whole 
point of this construct is to *dereference* a referential access (no special 
feature is needed to define a handle, after all, we've been doing that since 
the beginning of Ada time).

>> The ONLY reason that we need 4.1.5 is so that we can assign directly
>> into the target type.
>
> Yes, it is a hack designed for single use case.

There is no other need, everything else can be done with functions and 
procedures. Even this assignment can be done with a procedure, but such a 
procedure cannot compose or support extensions.

...
....
>> If you really wanted to go this way, you'd put all of those types in the
>> same class. (Having every possible advantage without any disadvantages is
>> impossible.) You are right about multiple dispatch in some cases, 
>> although
>> it's usually possible to layer those:
>>
>>     procedure Send (To : in out Register; Value : Data'Class);
>>
>> which is legal Ada.
>
> Sure, this is exactly how I do it. It bursts into dozens of generic
> packages and hundreds of their instances. Unless you propose to code all
> hundreds of combinations manually... How should I test THIS?

Testing is close to worthless. Ensure that the code is right in the first 
place (admittedly hard), and use a bit of testing for acceptance. Testing 
never proves any sort of correctness; all of the many thousands of hours of 
testing on our compiler never did anything to make it more reliable -- that 
all happened by better design. At best, the testing just prevented 
reintroduction of old bugs.

...
>> That's my point about static analysis. Such a tool should be able to 
>> prove
>> that the majority of run-time checks can't happen, and give you a list of
>> those remaining.
>
> I don't need any list. Should I send it to my customers? I need the 
> program
> fail to compile when writing analogue input.

Treat the list as failures if you must, and insist that it be empty before 
shipping. That's a reasonable approach in some environments. But I think 
you'll find it's too hard to accomplish, just like it's too hard to do 
complete code coverage (hard to test error handlers) and it's too hard to 
make everything generic. I'd rather prioritize such issues, and only worry 
about the ones in mainline code.

                                 Randy.


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

* Re: Is this expected behavior or not
  2013-03-25 22:24                                                                           ` Randy Brukardt
@ 2013-03-26  1:15                                                                             ` Shark8
  0 siblings, 0 replies; 242+ messages in thread
From: Shark8 @ 2013-03-26  1:15 UTC (permalink / raw)


On Monday, March 25, 2013 4:24:10 PM UTC-6, Randy Brukardt wrote:
> "Shark8" <onewingedshark@gmail.com> wrote in message 
> 
> news:c231e327-0859-4430-adfc-ed4de4de2208@googlegroups.com...
> 
> > On Friday, March 22, 2013 8:33:02 PM UTC-6, Randy Brukardt wrote:
> >>
> >> I'd never trust any program with more than a handful of generics, it's 
> >> just
> >> too hard to get the compilers to handle those right).
> >
> > That seems a bit odd... I would think that once you had a generic* method 
> > for handling overloading you could apply that to generics as well.
> >
> > [* Pun intended.]
> 
> It's the combination of a wealth of things, overloading is the easy one.

After posting -- and thinking about it a little more -- I did suspect that would be the case. {Though I would certainly love to hear the "whyfor" it's harder than overloading.}

> Certainly a shared implementation (like the one in Janus/Ada) makes 
> everything harder,

That reminds me: I need to consider getting a copy of Janus/Ada when/if I ever restart my OS-project idea. -- I do think an OS based entirely in Ada {except, *maybe*, the boot-loader} could be a much better foundation than the [general purpose] OSes we currently have.

> but there are enough oddities in the handling of formals 
> that it won't ever be easy.

Well, that's understandable given that generic [packages] have a lot more leeway in their 'discriminants' than discriminated-records. {According to http://www.cs.dartmouth.edu/reports/TR86-104.pdf records and generic-packages have a lot of overlap such that they are virtually entirely interchangeable... though this does raise the interesting possibility of unifying, on "the underside" of a compiler, a common format to handle both.}

But speaking of unifying things, would it make things easier to have Float and Fixed unified w/ a common base? {So that, say, one could have an algorithm parametrized w/ one or the other and still work -- that could be useful for DSP and other embedded systems.} Perhaps a Universal_Radix could be imagined as the 'Base of Universal_Fixed and Universal_Float, having all the asthmatic-functions [and aspects and attributes] common to both.

> It's really the result of having a strong 
> contract model for generics; that prevents using simple textual substitution 
> for thing.
>

I'm pretty sure textual substitution is almost always the wrong answer.
When I was working on a web-based program (handling medical records[!]) one of the modules included text-based merge-fields using textual substitution... it was horribly, horribly fragile.

> Of course, you need a strong contract model if you want the 
> generic to be correct without knowing anything about the instantiations. 
> (Same as you do for subprograms.)

True -- though if Ada does get a bit more attention/popularity there's likely going to be a push for the ARG to reduce contracts's strength. I think a lot of some [new to Ada] people's difficulties could be alleviated somewhat by subverting their wish to subvert the type-system with, perhaps, a user-defined attribute "To_Type'Convert( From_Type_Var )" used in much the same manner we handle stream-attributes... though it would have to support overloading (and I'm not sure that is such a good idea in an attribute).


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

* Re: Is this expected behavior or not
  2013-03-25 22:58                                                                           ` Randy Brukardt
@ 2013-03-26 10:52                                                                             ` Dmitry A. Kazakov
  2013-03-26 21:31                                                                               ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-26 10:52 UTC (permalink / raw)


On Mon, 25 Mar 2013 17:58:26 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:a96esjwiniqy$.op3wh7x9wrsl.dlg@40tude.net...
>> On Fri, 22 Mar 2013 21:33:02 -0500, Randy Brukardt wrote:
> ...
>>> That doesn't necessarily mean copying of the data. If the designer
>>> of the abstraction, have put in enough smarts to share representations --
>>> after all,
>>
>> You should break your mental block. No shared representation, I want
>> different representations for different string types.
> 
> I was talking about sharing representations of *different* objects of the 
> same string type (for instance, a string variable and a slice of that 
> variable - that case, sharing the data might be preferred to copying it).

OK, the representation would be for type-specific string objects:

   bounds + pointer

and for class-wide string objects:

   tag + bounds + pointer

>>>>> Slicing is already impossible for the case that we're talking about,
>>>>
>>>> ?
>>>>
>>>> Normal strings have slices and should continue to have them.
>>>
>>> Sure, but Root_String'Class is a separate type hierarchy.
>>
>> I see, yet another outhouse, also. Ada quickly becomes a shantytown...
> 
> Unifying old junk it's possible without serious breakage of existing code, 
> which is intolerable.

Why is it junk? There is nothing wrong with String, Wide_String,
Wide_Wide_String. They should stay.

Unbounded_String is indeed junk, but after adding an array interface to it
= putting it into the same hierarchy it would perfectly serve the purpose.

>> The way is to allow untagged T to have T'Class. This will preserve all
>> semantics and all existing representations. Not even an explicit root type
>> is needed, e.g. for char_array. The technique makes it possible to have
>> ad-hoc supertypes, which would serve the purpose, e.g. you would define
>> Put_Line on such a supertype and it will work for both String and
>> char_array. Not a line changed in Standard or Interfaces.C.
> 
> Sounds great, but it won't work in practice. You'd introduce a lot of 
> ambiguities and break existing code that way.

Why? The effect is limited strictly to T'Class objects, which presently do
not exist.

> (That's why 
> Ada.Strings.Unbounded_String doesn't have string literals; we couldn't find 
> any way to add them without making most existing code using the package 
> ambiguous.)

This is a different problem. I think the model is that string and other
literals would become primitive operations. Upon inheritance in the class
sense, they should be overridden or else dropped. There should be some
syntax invented for handling literals, e.g, some factory operation etc. An
alternative is having literals class-wide, which roughly corresponds to
existing Universal_String approach. In both cases you might wish to add
some preference rules [we already have some] to keep it compatible and
slash ambiguities. It would be worth to consider a possibility for the user
to control such preference rules and to have user-defined literals in
general.

> Secondly, the inheritance and overriding of untagged types is much looser 
> than the that of tagged types; you don't even have to use the same parameter 
> modes.

Yes, but untagged types in the model I have in mind will remain independent
types, they would not suddenly become Ada-subtypes, if you mean that. So

   subtype S is String ...;
   type Q is new String ...;

would have different semantics, just like they do for tagged types already.

> And dispatching is incompatible with untagged types, simply because Ada 83 
> got inheritance horribly wrong, and we're stuck with that.

I disagree. It seems fully compatible with Ada 83 because T'Class would be
a distinct type with objects of that type. It is orthogonal to
Ada-subtypes. You will not dispatch on Positive vs. Integer, these will
reman specific [sub]types. In order to dispatch you will need a class-wide
object of the type Integer'Class (which will be strictly same as
Positive'Class, except, possibly, the constraint). That object will have
the representation tag + value. For Integer and Positive objects nothing
changes. We might consider redefining some existing operations to become
class-wide in some arguments, but that is another story.

>>>> You have a very specific use case in mind, namely containers. There is a
>>>> whole world outside that, for which what you said is untrue, e.g. for
>>>> smart pointers. The thing not only exposes access, it also exposes the 
>>>> target type.
>>>
>>> You have to expose the target type in order to have strong typing. How 
>>> could you hide it and still make type checks?
>>
>> Why should target type be public?
> 
> How do you enforce strong typing without that being the case? If you don't 
> know what the target is, how do you determine how the resulting object can 
> be used?

Target and handle types usually implement some public interface. E.g.

   type File_Access is limited interface;
   procedure Write (File : in out File_Access; Data : ...) is abstract;
   ...

Somewhere else

   type File_Descriptor is ... limited ... and File_Access ...;

Somewhere else

   type File_Handle is ... and File_Access ...;

>>> If you really wanted to go this way, you'd put all of those types in the
>>> same class. (Having every possible advantage without any disadvantages is
>>> impossible.) You are right about multiple dispatch in some cases, 
>>> although it's usually possible to layer those:
>>>
>>>     procedure Send (To : in out Register; Value : Data'Class);
>>>
>>> which is legal Ada.
>>
>> Sure, this is exactly how I do it. It bursts into dozens of generic
>> packages and hundreds of their instances. Unless you propose to code all
>> hundreds of combinations manually... How should I test THIS?
> 
> Testing is close to worthless.

But this is the only choice if your checks are dynamic. If you don't like
testing then you should understand why I don't buy dynamic checks [mis]used
to detect bugs.

>>> That's my point about static analysis. Such a tool should be able to prove
>>> that the majority of run-time checks can't happen, and give you a list of
>>> those remaining.
>>
>> I don't need any list. Should I send it to my customers? I need the 
>> program fail to compile when writing analogue input.
> 
> Treat the list as failures if you must, and insist that it be empty before 
> shipping.

So, I need an AI system to parse compiler messages (of various vendors) on
top?

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


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

* Re: Is this expected behavior or not
  2013-03-26 10:52                                                                             ` Dmitry A. Kazakov
@ 2013-03-26 21:31                                                                               ` Randy Brukardt
  2013-03-27  9:37                                                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-26 21:31 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1u72u7h5j4jg3$.wlxmaltyzqik.dlg@40tude.net...
> On Mon, 25 Mar 2013 17:58:26 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:a96esjwiniqy$.op3wh7x9wrsl.dlg@40tude.net...
>>> On Fri, 22 Mar 2013 21:33:02 -0500, Randy Brukardt wrote:
>> ...
>>>> That doesn't necessarily mean copying of the data. If the designer
>>>> of the abstraction, have put in enough smarts to share 
>>>> representations --
>>>> after all,
>>>
>>> You should break your mental block. No shared representation, I want
>>> different representations for different string types.
>>
>> I was talking about sharing representations of *different* objects of the
>> same string type (for instance, a string variable and a slice of that
>> variable - that case, sharing the data might be preferred to copying it).
>
> OK, the representation would be for type-specific string objects:
>
>   bounds + pointer
>
> and for class-wide string objects:
>
>   tag + bounds + pointer

Sure, but irrelevant. The question is whether slicing copies the data or 
not. If it is a new object, the data must be copied logically, but my point 
was that it would be possible for an abstraction to defer actually making a 
copy until an assignment is actually done. It's still a copy.

...
>> Unifying old junk it's possible without serious breakage of existing 
>> code,
>> which is intolerable.
>
> Why is it junk? There is nothing wrong with String, Wide_String,
> Wide_Wide_String. They should stay.

They're junk because they can't be unified without serious breakage of 
existing code. Since we're not willing to break those eggs, we have to start 
over.

> Unbounded_String is indeed junk, but after adding an array interface to it
> = putting it into the same hierarchy it would perfectly serve the purpose.

That's the idea, but of course that requires starting over with it.

>>> The way is to allow untagged T to have T'Class. This will preserve all
>>> semantics and all existing representations. Not even an explicit root 
>>> type
>>> is needed, e.g. for char_array. The technique makes it possible to have
>>> ad-hoc supertypes, which would serve the purpose, e.g. you would define
>>> Put_Line on such a supertype and it will work for both String and
>>> char_array. Not a line changed in Standard or Interfaces.C.
>>
>> Sounds great, but it won't work in practice. You'd introduce a lot of
>> ambiguities and break existing code that way.
>
> Why? The effect is limited strictly to T'Class objects, which presently do
> not exist.

Not true, as I explained later in my note. The possibility of dispatching 
changes a lot of rules about inheritance and assignment.

>> (That's why
>> Ada.Strings.Unbounded_String doesn't have string literals; we couldn't 
>> find
>> any way to add them without making most existing code using the package
>> ambiguous.)
>
> This is a different problem. I think the model is that string and other
> literals would become primitive operations. Upon inheritance in the class
> sense, they should be overridden or else dropped. There should be some
> syntax invented for handling literals, e.g, some factory operation etc. An
> alternative is having literals class-wide, which roughly corresponds to
> existing Universal_String approach. In both cases you might wish to add
> some preference rules [we already have some] to keep it compatible and
> slash ambiguities. It would be worth to consider a possibility for the 
> user
> to control such preference rules and to have user-defined literals in
> general.

But that's not the problem; that was what we wanted to do. The problem is 
that Unbounded string has two versions of most operations, one that takes 
String and one that takes Unbounded_String. If you gave literals to 
Unbounded_String, all of the operations which took both would be ambiguous 
for literals unless you qualified them. Which defeats the purpose.

We could solve the problem by getting rid of all of the routines that take 
String parameters, but that of course woulc break any code that passed 
slices or objects of type String.

So the only fix here is to start over with a new package, keeping the old 
one around for existing code.

>> Secondly, the inheritance and overriding of untagged types is much looser
>> than the that of tagged types; you don't even have to use the same 
>> parameter
>> modes.
>
> Yes, but untagged types in the model I have in mind will remain 
> independent
> types, they would not suddenly become Ada-subtypes, if you mean that. So
>
>   subtype S is String ...;
>   type Q is new String ...;
>
> would have different semantics, just like they do for tagged types 
> already.
>
>> And dispatching is incompatible with untagged types, simply because Ada 
>> 83
>> got inheritance horribly wrong, and we're stuck with that.
>
> I disagree. It seems fully compatible with Ada 83 because T'Class would be
> a distinct type with objects of that type. It is orthogonal to
> Ada-subtypes. You will not dispatch on Positive vs. Integer, these will
> reman specific [sub]types. In order to dispatch you will need a class-wide
> object of the type Integer'Class (which will be strictly same as
> Positive'Class, except, possibly, the constraint). That object will have
> the representation tag + value. For Integer and Positive objects nothing
> changes. We might consider redefining some existing operations to become
> class-wide in some arguments, but that is another story.

You missed the point altogether. You can't dispatch in general on untagged 
types because overriding operations may have different modes and subtypes 
for the parameters. So what *is* the profile of the operation for T'Class, 
and how can it work?

Consider:

     Type Int is range 1 .. 10;
     procedure Op (A, B : in Int);

     Type Der is new Int;
     overriding
     procedure Op (A : in out Der; B : in Der);

     Obj : Int'Class := Der'(1);
     Op (A => 1, B => Obj); -- Legal??

Here, we're dispatching to a routine with an "in out" parameter, passing a 
literal (because the profile of Op for Int'Class has an "in" parameter). Is 
this legal? If so, what does it mean? If not, how does that work if Der is 
added to the program later during maintenance.

And if you say that Der cannot override Op this way, you're now incompatible 
with Ada 83- Ada 2012.

>>>>> You have a very specific use case in mind, namely containers. There is 
>>>>> a
>>>>> whole world outside that, for which what you said is untrue, e.g. for
>>>>> smart pointers. The thing not only exposes access, it also exposes the
>>>>> target type.
>>>>
>>>> You have to expose the target type in order to have strong typing. How
>>>> could you hide it and still make type checks?
>>>
>>> Why should target type be public?
>>
>> How do you enforce strong typing without that being the case? If you 
>> don't
>> know what the target is, how do you determine how the resulting object 
>> can
>> be used?
>
> Target and handle types usually implement some public interface. E.g.
>
>   type File_Access is limited interface;
>   procedure Write (File : in out File_Access; Data : ...) is abstract;
>   ...
>
> Somewhere else
>
>   type File_Descriptor is ... limited ... and File_Access ...;
>
> Somewhere else
>
>   type File_Handle is ... and File_Access ...;

An interface can't have "..." as the parameter type for Write; there has to 
be something there. And that's the target type! Say again how it is that you 
are not exposing this type??

...
>>>> That's my point about static analysis. Such a tool should be able to 
>>>> prove
>>>> that the majority of run-time checks can't happen, and give you a list 
>>>> of
>>>> those remaining.
>>>
>>> I don't need any list. Should I send it to my customers? I need the
>>> program fail to compile when writing analogue input.
>>
>> Treat the list as failures if you must, and insist that it be empty 
>> before
>> shipping.
>
> So, I need an AI system to parse compiler messages (of various vendors) on
> top?

Huh? Why would you "parse" them? It's a binary choice (just as it is with 
ACATS testing): either require them to be removed or ignored. You only have 
to decide which classes of warnings you require to be removed from your 
code. For that, you have to understand your tools, sure, but if you don't 
understand your tools you are never going to get anywhere. A programming 
language definition is only a small part of getting programming right; it 
could never be more than 10% or so; the tools used provide another 20-30%. 
The rest is on the programmer's skills (to do good things like decrease 
coupling).

                                    Randy.




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

* Re: Is this expected behavior or not
  2013-03-26 21:31                                                                               ` Randy Brukardt
@ 2013-03-27  9:37                                                                                 ` Dmitry A. Kazakov
  2013-03-27 19:42                                                                                   ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-27  9:37 UTC (permalink / raw)


On Tue, 26 Mar 2013 16:31:35 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1u72u7h5j4jg3$.wlxmaltyzqik.dlg@40tude.net...
>> On Mon, 25 Mar 2013 17:58:26 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:a96esjwiniqy$.op3wh7x9wrsl.dlg@40tude.net...
>>>> On Fri, 22 Mar 2013 21:33:02 -0500, Randy Brukardt wrote:
>>> ...
>>>>> That doesn't necessarily mean copying of the data. If the designer
>>>>> of the abstraction, have put in enough smarts to share 
>>>>> representations --
>>>>> after all,
>>>>
>>>> You should break your mental block. No shared representation, I want
>>>> different representations for different string types.
>>>
>>> I was talking about sharing representations of *different* objects of the
>>> same string type (for instance, a string variable and a slice of that
>>> variable - that case, sharing the data might be preferred to copying it).
>>
>> OK, the representation would be for type-specific string objects:
>>
>>   bounds + pointer
>>
>> and for class-wide string objects:
>>
>>   tag + bounds + pointer
> 
> Sure, but irrelevant. The question is whether slicing copies the data or 
> not. If it is a new object, the data must be copied logically,

No, logically it is a referential object.

> but my point 
> was that it would be possible for an abstraction to defer actually making a 
> copy until an assignment is actually done. It's still a copy.

Exactly the reverse, an implementation could be allowed to use a copy if
that is consistent with the semantics of the slice being a reference.

But regardless of the semantics, why this representation should not work?

>>> Unifying old junk it's possible without serious breakage of existing 
>>> code, which is intolerable.
>>
>> Why is it junk? There is nothing wrong with String, Wide_String,
>> Wide_Wide_String. They should stay.
> 
> They're junk because they can't be unified without serious breakage of 
> existing code.

A common ancestor would not break existing code. An ad-hoc ancestor could
not do it even theoretically, because it is limited to the context where
the ancestor is visible.

>>> And dispatching is incompatible with untagged types, simply because Ada 
>>> 83 got inheritance horribly wrong, and we're stuck with that.
>>
>> I disagree. It seems fully compatible with Ada 83 because T'Class would be
>> a distinct type with objects of that type. It is orthogonal to
>> Ada-subtypes. You will not dispatch on Positive vs. Integer, these will
>> reman specific [sub]types. In order to dispatch you will need a class-wide
>> object of the type Integer'Class (which will be strictly same as
>> Positive'Class, except, possibly, the constraint). That object will have
>> the representation tag + value. For Integer and Positive objects nothing
>> changes. We might consider redefining some existing operations to become
>> class-wide in some arguments, but that is another story.
> 
> You missed the point altogether. You can't dispatch in general on untagged 
> types because overriding operations may have different modes and subtypes 
> for the parameters. So what *is* the profile of the operation for T'Class, 
> and how can it work?
> 
> Consider:
> 
>      Type Int is range 1 .. 10;
>      procedure Op (A, B : in Int);
> 
>      Type Der is new Int;

This is not derivation within the class, it is a "type-cloning." Type
cloning creates a new class and new a type (all types up the hierarchy). We
need some syntax to indicate the difference.

   type Der is new Int <whatever>;

It is unfortunate that tagged types reused "is new" for a purpose
completely different from type cloning.

Moreover, it is highly desired to that cloning were available for tagged
types as well:

   package Original is new Ada.Containers.Vectors ...;
   type Clone is new Original.Vector; -- Cloning, not extending!

Now, I have to hierarchies of Vector, not very useful in this particular
case, because of missing helper types, but anyway.

>      overriding
>      procedure Op (A : in out Der; B : in Der);

This is not an overriding since the mode is different.

>      Obj : Int'Class := Der'(1);
>      Op (A => 1, B => Obj); -- Legal??

MD is not fully implemented in Ada, but anyway, presuming that Op is a
multi-method, that the mode is "in" and that 1 is Universal_Integer (is
it?), the above is illegal because Op is not a method of
Universal_Integer'Class. You would have to write it as:

   Op (A => Der'(1), B => Obj);  -- Same tags
   Op (A => Int'(1), B => Obj);  -- Different tags, Constraint_Error

Multi-methods (a special case of MD) is another and long story. They should
be properly supported in the end.

> And if you say that Der cannot override Op this way, you're now incompatible 
> with Ada 83- Ada 2012.

I want to preserve and extend type-cloning.
 
>>>>>> You have a very specific use case in mind, namely containers. There is a
>>>>>> whole world outside that, for which what you said is untrue, e.g. for
>>>>>> smart pointers. The thing not only exposes access, it also exposes the
>>>>>> target type.
>>>>>
>>>>> You have to expose the target type in order to have strong typing. How
>>>>> could you hide it and still make type checks?
>>>>
>>>> Why should target type be public?
>>>
>>> How do you enforce strong typing without that being the case? If you don't
>>> know what the target is, how do you determine how the resulting object can
>>> be used?
>>
>> Target and handle types usually implement some public interface. E.g.
>>
>>   type File_Access is limited interface;
>>   procedure Write (File : in out File_Access; Data : ...) is abstract;
>>   ...
>>
>> Somewhere else
>>
>>   type File_Descriptor is ... limited ... and File_Access ...;
>>
>> Somewhere else
>>
>>   type File_Handle is ... and File_Access ...;
> 
> An interface can't have "..." as the parameter type for Write; there has to 
> be something there.

   procedure Write (File : in out File_Access; Data : Stream_Element_Array)
      is abstract;

> And that's the target type! Say again how it is that you 
> are not exposing this type??

The target is File. I would gladly have MD and a hierarchy for the second
parameter, but that is another story for now.

>>>>> That's my point about static analysis. Such a tool should be able to prove
>>>>> that the majority of run-time checks can't happen, and give you a list of
>>>>> those remaining.
>>>>
>>>> I don't need any list. Should I send it to my customers? I need the
>>>> program fail to compile when writing analogue input.
>>>
>>> Treat the list as failures if you must, and insist that it be empty 
>>> before shipping.
>>
>> So, I need an AI system to parse compiler messages (of various vendors) on
>> top?
> 
> Huh? Why would you "parse" them?

Because whether a message is relevant to the choice if the program were OK
to deploy depends now on the message content. The language does not help me
anymore to indicate it as a bug.

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


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

* Re: Is this expected behavior or not
  2013-03-27  9:37                                                                                 ` Dmitry A. Kazakov
@ 2013-03-27 19:42                                                                                   ` Randy Brukardt
  2013-03-28 13:50                                                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-27 19:42 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:wdlyfbnwcnp7.10c9btwjmpm7j.dlg@40tude.net...
> On Tue, 26 Mar 2013 16:31:35 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1u72u7h5j4jg3$.wlxmaltyzqik.dlg@40tude.net...
>>> On Mon, 25 Mar 2013 17:58:26 -0500, Randy Brukardt wrote:
>>>
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>>> news:a96esjwiniqy$.op3wh7x9wrsl.dlg@40tude.net...
>>>>> On Fri, 22 Mar 2013 21:33:02 -0500, Randy Brukardt wrote:
>>>> ...
>>>>>> That doesn't necessarily mean copying of the data. If the designer
>>>>>> of the abstraction, have put in enough smarts to share
>>>>>> representations --
>>>>>> after all,
>>>>>
>>>>> You should break your mental block. No shared representation, I want
>>>>> different representations for different string types.
>>>>
>>>> I was talking about sharing representations of *different* objects of 
>>>> the
>>>> same string type (for instance, a string variable and a slice of that
>>>> variable - that case, sharing the data might be preferred to copying 
>>>> it).
>>>
>>> OK, the representation would be for type-specific string objects:
>>>
>>>   bounds + pointer
>>>
>>> and for class-wide string objects:
>>>
>>>   tag + bounds + pointer
>>
>> Sure, but irrelevant. The question is whether slicing copies the data or
>> not. If it is a new object, the data must be copied logically,
>
> No, logically it is a referential object.
>
>> but my point
>> was that it would be possible for an abstraction to defer actually making 
>> a
>> copy until an assignment is actually done. It's still a copy.
>
> Exactly the reverse, an implementation could be allowed to use a copy if
> that is consistent with the semantics of the slice being a reference.
>
> But regardless of the semantics, why this representation should not work?

The problem is that a slice ought to be a referential object as you put it, 
and a "regular" object is definitely *not* a referential object (a copy 
copies the data). I don't see any way for a single data type to have two 
different behaviors - as you've argued elsewhere, you can't have a single 
operation doing two different things. I suppose you could make a slice be a 
different type than a regular string object, but then you have problems with 
type matching (you want a slice to be compatible with the equivalent normal 
object).

...
>>>> And dispatching is incompatible with untagged types, simply because Ada
>>>> 83 got inheritance horribly wrong, and we're stuck with that.
>>>
>>> I disagree. It seems fully compatible with Ada 83 because T'Class would 
>>> be
>>> a distinct type with objects of that type. It is orthogonal to
>>> Ada-subtypes. You will not dispatch on Positive vs. Integer, these will
>>> reman specific [sub]types. In order to dispatch you will need a 
>>> class-wide
>>> object of the type Integer'Class (which will be strictly same as
>>> Positive'Class, except, possibly, the constraint). That object will have
>>> the representation tag + value. For Integer and Positive objects nothing
>>> changes. We might consider redefining some existing operations to become
>>> class-wide in some arguments, but that is another story.
>>
>> You missed the point altogether. You can't dispatch in general on 
>> untagged
>> types because overriding operations may have different modes and subtypes
>> for the parameters. So what *is* the profile of the operation for 
>> T'Class,
>> and how can it work?
>>
>> Consider:
>>
>>      Type Int is range 1 .. 10;
>>      procedure Op (A, B : in Int);
>>
>>      Type Der is new Int;
>
> This is not derivation within the class, it is a "type-cloning." Type
> cloning creates a new class and new a type (all types up the hierarchy). 
> We
> need some syntax to indicate the difference.
>
>   type Der is new Int <whatever>;
>
> It is unfortunate that tagged types reused "is new" for a purpose
> completely different from type cloning.

Nobody wants "type cloning". We waste a lot of mental energy getting rid of 
it in generics, for example. I have no idea why anyone that wants 'Class 
would want to avoid maximizing the interoperability of types. The original 
motivating example for Integer'Class was:

     Put (Obj : Integer'Class; Width : Count := 0);

so that one didn't need to understand generic instantiations just to do 
simple I/O of strongly typed entities.

I don't think a version of untagged'Class that did not work on existing 
derived types would fly. For no other reason than the fact that it would 
make tagged and untagged types more different, rather than less different.

In any case, I didn't realize that you were making an entire new kind of 
type derivation - I wouldn't have guessed that someone that has been talking 
repeatedly about simplifying the language would add an entirely new kind of 
type to the language.

> Moreover, it is highly desired to that cloning were available for tagged
> types as well:
>
>   package Original is new Ada.Containers.Vectors ...;
>   type Clone is new Original.Vector; -- Cloning, not extending!
>
> Now, I have to hierarchies of Vector, not very useful in this particular
> case, because of missing helper types, but anyway.

Pointless complication. I thought you were trying to simplify the language!

>>      overriding
>>      procedure Op (A : in out Der; B : in Der);
>
> This is not an overriding since the mode is different.

It *is* an overriding in Ada 83, and it still is in Ada 2012. I agree that 
it should not have been, but that is irrelevant because we're stuck with it.

>>      Obj : Int'Class := Der'(1);
>>      Op (A => 1, B => Obj); -- Legal??
>
> MD is not fully implemented in Ada, but anyway, presuming that Op is a
> multi-method, that the mode is "in" and that 1 is Universal_Integer (is
> it?), the above is illegal because Op is not a method of
> Universal_Integer'Class. You would have to write it as:
>
>   Op (A => Der'(1), B => Obj);  -- Same tags
>   Op (A => Int'(1), B => Obj);  -- Different tags, Constraint_Error

This seems wrong; an integer literal usually gets its type from context. 
It's only a value of type Universal_Integer if there is no type given from 
context (as in a type conversion or number declaration). I was presuming 
that integer literals act as tag-indeterminate functions (the most sensible 
model; if you have constants for a tagged type you usually would model them 
as tag-indeterminate functions - for instance, the constants Zero and One in 
a universal arithmetic package), you don't need multiple dispatch: the Ada 
dispatching rules simply calls the correct version of the function for the 
tag of the object. And that's what we would want to happen for integer 
literals (that's the closest analogy to what happens for existing 
expressions).

> Multi-methods (a special case of MD) is another and long story. They 
> should
> be properly supported in the end.
>
>> And if you say that Der cannot override Op this way, you're now 
>> incompatible
>> with Ada 83- Ada 2012.
>
> I want to preserve and extend type-cloning.

And you claim that the ARG keeps building gazebos. You're building a 
lakeside floating pavillion. ;-)

...
>> An interface can't have "..." as the parameter type for Write; there has 
>> to
>> be something there.
>
>   procedure Write (File : in out File_Access; Data : Stream_Element_Array)
>      is abstract;
>
>> And that's the target type! Say again how it is that you
>> are not exposing this type??
>
> The target is File. I would gladly have MD and a hierarchy for the second
> parameter, but that is another story for now.

OK, if the target is File, then you know that - that's public information. 
When you dereference a File_Handle, you get a File. You don't have to make 
the contents of File public, just it's name. So I still don't see why you 
think this is a problem.

>>>>>> That's my point about static analysis. Such a tool should be able to 
>>>>>> prove
>>>>>> that the majority of run-time checks can't happen, and give you a 
>>>>>> list of
>>>>>> those remaining.
>>>>>
>>>>> I don't need any list. Should I send it to my customers? I need the
>>>>> program fail to compile when writing analogue input.
>>>>
>>>> Treat the list as failures if you must, and insist that it be empty
>>>> before shipping.
>>>
>>> So, I need an AI system to parse compiler messages (of various vendors) 
>>> on
>>> top?
>>
>> Huh? Why would you "parse" them?
>
> Because whether a message is relevant to the choice if the program were OK
> to deploy depends now on the message content. The language does not help 
> me
> anymore to indicate it as a bug.

But there is absolutely nothing new about this. GNAT has a variety of 
warnings (calling everything it displays a "warning" in order to avoid 
arguments about its particular classifications of message), but most people 
choose to treat some subset of them as errors that have to be removed before 
deployment. You would do that same; choose a *class* of warnings that have 
to be removed; there is no parsing of messages needed. If a warning in the 
prohibited class exists, the program is not ready for deployment.

Yes, this means you need to develop a coding standard and a development 
standard to ensure that these these things are followed. But not having 
those in some form is just lousy programming management. And one thing we 
decided on the ARG long ago is that there is no way that a programming 
language can prevent lousy programming management -- any language can be 
misused without much effort. That cannot be prevented by a programming 
language; it's futile to try, and when you do try, you tend to make the 
language harder to use on real problems. So we assume competent management 
is used with Ada; we're not trying to make the language idiot-proof.

                                            Randy.





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

* Re: Is this expected behavior or not
  2013-03-27 19:42                                                                                   ` Randy Brukardt
@ 2013-03-28 13:50                                                                                     ` Dmitry A. Kazakov
  2013-03-28 21:55                                                                                       ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-28 13:50 UTC (permalink / raw)


On Wed, 27 Mar 2013 14:42:47 -0500, Randy Brukardt wrote:

> The problem is that a slice ought to be a referential object as you put it, 
> and a "regular" object is definitely *not* a referential object (a copy 
> copies the data).

What is "regular" object here? String?

> I don't see any way for a single data type to have two 
> different behaviors

These are two data types, string and slice. Are you treating slice as an
Ada-subtype of string? I consider slice a member of same class as string,
yet a distinct type (in Ada sense). This is like 4.1.5, but in the same
type hierarchy.

>>> You missed the point altogether. You can't dispatch in general on untagged
>>> types because overriding operations may have different modes and subtypes
>>> for the parameters. So what *is* the profile of the operation for T'Class,
>>> and how can it work?
>>>
>>> Consider:
>>>
>>>      Type Int is range 1 .. 10;
>>>      procedure Op (A, B : in Int);
>>>
>>>      Type Der is new Int;
>>
>> This is not derivation within the class, it is a "type-cloning." Type
>> cloning creates a new class and new a type (all types up the hierarchy). 
>> We need some syntax to indicate the difference.
>>
>>   type Der is new Int <whatever>;
>>
>> It is unfortunate that tagged types reused "is new" for a purpose
>> completely different from type cloning.
> 
> Nobody wants "type cloning".

It is a very useful building block to me. Anyway it is Ada 83 legacy.

> I have no idea why anyone that wants 'Class 
> would want to avoid maximizing the interoperability of types.

Sometimes we want types related, sometimes we don't, while reusing existing
implementations. The language should support programmer's choice.

> The original motivating example for Integer'Class was:
> 
>      Put (Obj : Integer'Class; Width : Count := 0);
> 
> so that one didn't need to understand generic instantiations just to do 
> simple I/O of strongly typed entities.

Yes.

Cloned Integer will "inherit" this Put operation in Ada 83 sense. Ada 83
cloning is orthogonal to type hierarchies. You get a new hierarchy when you
clone a type.

> I don't think a version of untagged'Class that did not work on existing 
> derived types would fly.

Astonishing that you even considered that possibility. In my view they are
completely independent things.

> In any case, I didn't realize that you were making an entire new kind of 
> type derivation

To me it is exactly same as tagged extension when you add nothing to the
existing representation.

We also need "extension" that drops parent's representation altogether.
E.g. something like:

   type Character is new Unsigned_8 -- or enumeration, whatever
      and Wide_Wide_Character'Interface;

Character is member of Wide_Wide_Character'Class with a representation
different from Wide_Wide_Character.

>> Moreover, it is highly desired to that cloning were available for tagged
>> types as well:
>>
>>   package Original is new Ada.Containers.Vectors ...;
>>   type Clone is new Original.Vector; -- Cloning, not extending!
>>
>> Now, I have to hierarchies of Vector, not very useful in this particular
>> case, because of missing helper types, but anyway.
> 
> Pointless complication. I thought you were trying to simplify the language!

Making it regular is a simplification.

>>>      overriding
>>>      procedure Op (A : in out Der; B : in Der);
>>
>> This is not an overriding since the mode is different.
> 
> It *is* an overriding in Ada 83, and it still is in Ada 2012. I agree that 
> it should not have been, but that is irrelevant because we're stuck with it.

Only when Der is derived using Ada 83 construct. Int'Class will be built
using "extension."

>>>      Obj : Int'Class := Der'(1);
>>>      Op (A => 1, B => Obj); -- Legal??
>>
>> MD is not fully implemented in Ada, but anyway, presuming that Op is a
>> multi-method, that the mode is "in" and that 1 is Universal_Integer (is
>> it?), the above is illegal because Op is not a method of
>> Universal_Integer'Class. You would have to write it as:
>>
>>   Op (A => Der'(1), B => Obj);  -- Same tags
>>   Op (A => Int'(1), B => Obj);  -- Different tags, Constraint_Error
> 
> This seems wrong; an integer literal usually gets its type from context. 
> It's only a value of type Universal_Integer if there is no type given from 
> context (as in a type conversion or number declaration). I was presuming 
> that integer literals act as tag-indeterminate functions (the most sensible 
> model; if you have constants for a tagged type you usually would model them 
> as tag-indeterminate functions - for instance, the constants Zero and One in 
> a universal arithmetic package), you don't need multiple dispatch: the Ada 
> dispatching rules simply calls the correct version of the function for the 
> tag of the object. And that's what we would want to happen for integer 
> literals (that's the closest analogy to what happens for existing 
> expressions).

This is one of possible interpretations of Ada semantics. You consider
literals primitive operations, e.g.

   function "1" return Int;

In Ada 95 such function has to be overridden, when Der extends Int.
However, if the representation is inherited and not changed, the rule could
be that the compiler silently overrides all literals:

   overriding function "1" return Der;

In this case you will have 1 overloaded. Op will become ambiguous. The
alternative with different types can be discarded using some preference
rules, e.g. domination, and thus ambiguity resolved.

>>> An interface can't have "..." as the parameter type for Write; there has 
>>> to be something there.
>>
>>   procedure Write (File : in out File_Access; Data : Stream_Element_Array)
>>      is abstract;
>>
>>> And that's the target type! Say again how it is that you
>>> are not exposing this type??
>>
>> The target is File. I would gladly have MD and a hierarchy for the second
>> parameter, but that is another story for now.
> 
> OK, if the target is File, then you know that - that's public information. 
> When you dereference a File_Handle, you get a File. You don't have to make 
> the contents of File public, just it's name. So I still don't see why you 
> think this is a problem.

I don't want to expose File at all. Public views should have no access to
it, otherwise than indirectly through the handle. E.g. they should not be
able to get an access the file object, store it somewhere, deallocate it,
use stream attributes on it, and perform any other fancy stuff.
Furthermore, later on, a decision may fall to replace file descriptor with
something completely different keeping code that uses handles intact. It is
good old information hiding principle.

>> Because whether a message is relevant to the choice if the program were OK
>> to deploy depends now on the message content. The language does not help 
>> me anymore to indicate it as a bug.
> 
> But there is absolutely nothing new about this.

There is nothing new that people die, yet nobody actually likes it.

> GNAT has a variety of 
> warnings (calling everything it displays a "warning" in order to avoid 
> arguments about its particular classifications of message), but most people 
> choose to treat some subset of them as errors that have to be removed before 
> deployment. You would do that same; choose a *class* of warnings that have 
> to be removed; there is no parsing of messages needed. If a warning in the 
> prohibited class exists, the program is not ready for deployment.

Some C compilers give warning when you write:

   if (x = 1) ...

> Yes, this means you need to develop a coding standard and a development 
> standard to ensure that these these things are followed. But not having 
> those in some form is just lousy programming management.

Error checks do not belong to coding standards. Coding standard, and
testing, and code review etc are there when compiler checks were
impossible.

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

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

* Re: Is this expected behavior or not
  2013-03-28 13:50                                                                                     ` Dmitry A. Kazakov
@ 2013-03-28 21:55                                                                                       ` Randy Brukardt
  2013-03-29 12:26                                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-03-28 21:55 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:cqf0yy6q930$.1sdzw45bc0c1w.dlg@40tude.net...
> On Wed, 27 Mar 2013 14:42:47 -0500, Randy Brukardt wrote:
>
>> The problem is that a slice ought to be a referential object as you put 
>> it,
>> and a "regular" object is definitely *not* a referential object (a copy
>> copies the data).
>
> What is "regular" object here? String?

A non-slice string object.

>> I don't see any way for a single data type to have two
>> different behaviors
>
> These are two data types, string and slice. Are you treating slice as an
> Ada-subtype of string? I consider slice a member of same class as string,
> yet a distinct type (in Ada sense). This is like 4.1.5, but in the same
> type hierarchy.

I thought you might do that, but then you're going to have problems of 
compatibility (Ada currently considers them the same type). An operation 
like "&" cannot not allow mixed string operands (if you do allow that, you 
make string literals ambiguous).

...
>> Nobody wants "type cloning".
>
> It is a very useful building block to me. Anyway it is Ada 83 legacy.

Ada 83 derived types are virtually useless, and no one understood how they 
worked. I objected to building tagged types on that foundation during Ada 
9x, but they didn't pay any attention to me on that. :-)

Ada 83 derived types would be one of the first things to get rid of in a new 
Ada-like language -- everything should be related. Indeed, all integer types 
belong to Root_Integer'Class (you just can't name that type in Ada as it 
stands); it would be weird to *break* that.

 ...
>> I don't think a version of untagged'Class that did not work on existing
>> derived types would fly.
>
> Astonishing that you even considered that possibility. In my view they are
> completely independent things.

You really have a strange mind. The whole idea of 'Class is to allow 
different but related types to share implementations. You're only allowed to 
convert between related types, which includes derived types.

>> In any case, I didn't realize that you were making an entire new kind of
>> type derivation
>
> To me it is exactly same as tagged extension when you add nothing to the
> existing representation.

Sure, this I totally agree with. But those are highly related to each other: 
Parent'Class includes the parent and the derivation.

> We also need "extension" that drops parent's representation altogether.
> E.g. something like:
>
>   type Character is new Unsigned_8 -- or enumeration, whatever
>      and Wide_Wide_Character'Interface;
>
> Character is member of Wide_Wide_Character'Class with a representation
> different from Wide_Wide_Character.

I don't think that would work semantically, at least in the 'Class case. 
Unless you expect every operation down to assigning individual components to 
be dispatching, even in primitive routines defined for a specific type. 
That's because you can't copy all tagged types (we have to have limited 
types), and thus calling a parent operation would have to assume that 
extensions have a different representation. That would both have problems of 
re-dispatch and simply would be awfully expensive (you'd have to do full 
program compilation to have any hope of decent code).

The only alternative would be to totally ban implementation inheritance on 
such types, but as implementation inheritance is 10 times more useful than 
interface inheritance, it would make the construct 95% useless.

>>> Moreover, it is highly desired to that cloning were available for tagged
>>> types as well:
>>>
>>>   package Original is new Ada.Containers.Vectors ...;
>>>   type Clone is new Original.Vector; -- Cloning, not extending!
>>>
>>> Now, I have to hierarchies of Vector, not very useful in this particular
>>> case, because of missing helper types, but anyway.
>>
>> Pointless complication. I thought you were trying to simplify the 
>> language!
>
> Making it regular is a simplification.

This isn't regular. All numeric types are currently members of a single 
hierarchy, and in practice, the vast majority of tagged types are members of 
two hierarchies (controlled and limited controlled). If I was going to 
simplify this further, I would make all of these into a single hierarchy. 
More hierarchies don't buy anything (you can always move your 'Classes 
around in the hierarchy to get subsets).

>>>>      overriding
>>>>      procedure Op (A : in out Der; B : in Der);
>>>
>>> This is not an overriding since the mode is different.
>>
>> It *is* an overriding in Ada 83, and it still is in Ada 2012. I agree 
>> that
>> it should not have been, but that is irrelevant because we're stuck with 
>> it.
>
> Only when Der is derived using Ada 83 construct. Int'Class will be built
> using "extension."

No way; derived types currently form a hierarchy (that's why you can 
interconvert them); changing that would require fundamentally changing the 
Ada model of hierarchies. The issue today is that you can't name those 
hierarchies, that's what untagged 'Class would allow.

>>>>      Obj : Int'Class := Der'(1);
>>>>      Op (A => 1, B => Obj); -- Legal??
>>>
>>> MD is not fully implemented in Ada, but anyway, presuming that Op is a
>>> multi-method, that the mode is "in" and that 1 is Universal_Integer (is
>>> it?), the above is illegal because Op is not a method of
>>> Universal_Integer'Class. You would have to write it as:
>>>
>>>   Op (A => Der'(1), B => Obj);  -- Same tags
>>>   Op (A => Int'(1), B => Obj);  -- Different tags, Constraint_Error
>>
>> This seems wrong; an integer literal usually gets its type from context.
>> It's only a value of type Universal_Integer if there is no type given 
>> from
>> context (as in a type conversion or number declaration). I was presuming
>> that integer literals act as tag-indeterminate functions (the most 
>> sensible
>> model; if you have constants for a tagged type you usually would model 
>> them
>> as tag-indeterminate functions - for instance, the constants Zero and One 
>> in
>> a universal arithmetic package), you don't need multiple dispatch: the 
>> Ada
>> dispatching rules simply calls the correct version of the function for 
>> the
>> tag of the object. And that's what we would want to happen for integer
>> literals (that's the closest analogy to what happens for existing
>> expressions).
>
> This is one of possible interpretations of Ada semantics. You consider
> literals primitive operations, e.g.
>
>   function "1" return Int;
>
> In Ada 95 such function has to be overridden, when Der extends Int.
> However, if the representation is inherited and not changed, the rule 
> could
> be that the compiler silently overrides all literals:
>
>   overriding function "1" return Der;
>
> In this case you will have 1 overloaded. Op will become ambiguous.

Yes, this is how Ada literals work today. This isn't how its described (it's 
an implicit conversion rather than overloading) but the effect is the same.

> The alternative with different types can be discarded using some 
> preference
> rules, e.g. domination, and thus ambiguity resolved.

Preference rules cause Beaujolias effects, and almost never can be 
tolerated. Ada used to have some for literals and they caused all manner of 
problems. The preference rules for universal causes problems as well (as you 
are pointing out here); these are extremely fragile and only work because 
universal types can't have any user-defined operations or visibility 
changes.

As soon as user-defined things are involved, preference rules simply don't 
work. Maybe they would work in a language without nesting and private parts 
and use clauses, but they don't work in Ada. (The problem being that adding 
or removing a single declaration can silently change the meaning of an 
expression without causing an error. This is considered intolerable.)

>>>> An interface can't have "..." as the parameter type for Write; there 
>>>> has
>>>> to be something there.
>>>
>>>   procedure Write (File : in out File_Access; Data : 
>>> Stream_Element_Array)
>>>      is abstract;
>>>
>>>> And that's the target type! Say again how it is that you
>>>> are not exposing this type??
>>>
>>> The target is File. I would gladly have MD and a hierarchy for the 
>>> second
>>> parameter, but that is another story for now.
>>
>> OK, if the target is File, then you know that - that's public 
>> information.
>> When you dereference a File_Handle, you get a File. You don't have to 
>> make
>> the contents of File public, just it's name. So I still don't see why you
>> think this is a problem.
>
> I don't want to expose File at all. Public views should have no access to
> it, otherwise than indirectly through the handle. E.g. they should not be
> able to get an access the file object, store it somewhere, deallocate it,
> use stream attributes on it, and perform any other fancy stuff.
> Furthermore, later on, a decision may fall to replace file descriptor with
> something completely different keeping code that uses handles intact. It 
> is
> good old information hiding principle.

Fine. But then you don't need any user-visible dereferencing, and you surely 
wouldn't use it. My contention remains: if you are going to allow user 
"Handle.all", then you need to expose the type of Handle.all. If you don't 
need to allow that, then you are not going to use 4.1.5 at all. So I fail to 
see your concern.

>>> Because whether a message is relevant to the choice if the program were 
>>> OK
>>> to deploy depends now on the message content. The language does not help
>>> me anymore to indicate it as a bug.
>>
>> But there is absolutely nothing new about this.
>
> There is nothing new that people die, yet nobody actually likes it.
>
>> GNAT has a variety of
>> warnings (calling everything it displays a "warning" in order to avoid
>> arguments about its particular classifications of message), but most 
>> people
>> choose to treat some subset of them as errors that have to be removed 
>> before
>> deployment. You would do that same; choose a *class* of warnings that 
>> have
>> to be removed; there is no parsing of messages needed. If a warning in 
>> the
>> prohibited class exists, the program is not ready for deployment.
>
> Some C compilers give warning when you write:
>
>   if (x = 1) ...
>
>> Yes, this means you need to develop a coding standard and a development
>> standard to ensure that these these things are followed. But not having
>> those in some form is just lousy programming management.
>
> Error checks do not belong to coding standards. Coding standard, and
> testing, and code review etc are there when compiler checks were
> impossible.

Compiler checks are impossible for these things. Unless you want to drive 
yourself nuts with OOP baloney - and it's never going to be possible to do 
these sorts of checks with type checking. (This is not a type problem, it's 
a subtype (in the Ada sense) problem.) Feel free to pick your poison, as it 
will, but expecting types to do all of the work is just as silly as 
expecting that you can make a correct program with defining any types at 
all.

                                       Randy.





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

* Re: Is this expected behavior or not
  2013-03-28 21:55                                                                                       ` Randy Brukardt
@ 2013-03-29 12:26                                                                                         ` Dmitry A. Kazakov
  2013-03-30  0:49                                                                                           ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-29 12:26 UTC (permalink / raw)


On Thu, 28 Mar 2013 16:55:34 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:cqf0yy6q930$.1sdzw45bc0c1w.dlg@40tude.net...

>> These are two data types, string and slice. Are you treating slice as an
>> Ada-subtype of string? I consider slice a member of same class as string,
>> yet a distinct type (in Ada sense). This is like 4.1.5, but in the same
>> type hierarchy.
> 
> I thought you might do that, but then you're going to have problems of 
> compatibility (Ada currently considers them the same type). An operation 
> like "&" cannot not allow mixed string operands (if you do allow that, you 
> make string literals ambiguous).

Right, if strings form a hierarchy, then "&" must be primitive and a
multi-method. There is no alternative to that. Even if you are going to add
a completely new set of string types without slices you still will have
this problem:

   declare
        X : New_String_Type;
        Y : A_Descendant_Of;
    begin
        ... X & Y ...;  -- Is this legal? Does it raise Constraint_Error?

The answers must be yes, no. And for this "&" must be a multi-method with
all combinations of argument and the result types defined. Making some of
them class-wide could reduce the number of combinations. And it will be
ambiguous with literals and other overloaded operations returning string
objects.

>>> Nobody wants "type cloning".
>>
>> It is a very useful building block to me. Anyway it is Ada 83 legacy.
> 
> Ada 83 derived types are virtually useless, and no one understood how they 
> worked.

What would you do if you need a new type with same properties. Copy-paste?
Example:

   type Position is <some positive number>;
   type Key is some <some positive number>;
   type Container is ...;

How do you prevent Position and Key mixed in Container operations if they
belong to same hierarchy?

>>> I don't think a version of untagged'Class that did not work on existing
>>> derived types would fly.
>>
>> Astonishing that you even considered that possibility. In my view they are
>> completely independent things.
> 
> You really have a strange mind. The whole idea of 'Class is to allow 
> different but related types to share implementations.

Yes, if "implementation" means class-wide and inherited operations. The
idea of T'Class is to share an interface, so that programs could be written
in terms of the interface, which would make them working on all instances
of the class (AKA, generic programming). We want to have this for all types
including those which representations are different. If you want to be able
to inherit an operation for such a type, the only way to do it is to
compose old body with type representation conversion. This is the model for
untagged classes. You will be free to derive from any non-limited type
ignoring its representation, but then the compiler will ask you either to
override an inherited primitive operation or else define corresponding
conversions so that it could create one.

> You're only allowed to 
> convert between related types, which includes derived types.

That is the only way to have a class without sharing (inheriting, actually)
representations.

The model of Ada 95 tagged types provides a class with shared
representations. This need to be augmented for the case when
representations has to be different. Note that this was partially done when
Java interfaces were added in Ada 2005. Java interface is a type without
any representation, so there is nothing to inherit from, except for a slot
for the type tag. Drop that slot, and you will have a workable model for
building classes of scalar types and arrays.

>> We also need "extension" that drops parent's representation altogether.
>> E.g. something like:
>>
>>   type Character is new Unsigned_8 -- or enumeration, whatever
>>      and Wide_Wide_Character'Interface;
>>
>> Character is member of Wide_Wide_Character'Class with a representation
>> different from Wide_Wide_Character.
> 
> I don't think that would work semantically, at least in the 'Class case. 
> Unless you expect every operation down to assigning individual components to 
> be dispatching, even in primitive routines defined for a specific type.

Exactly! I want all that mess to become orderly defined primitive
operations. This also includes attributes and aspects. There should be no
special cases like T'Read, ":=" etc. There should be no magic and strange
stuff like attributes, slices, ranges, aspects infesting the language, only
objects and operations.

> That's because you can't copy all tagged types (we have to have limited 
> types), and thus calling a parent operation would have to assume that 
> extensions have a different representation. That would both have problems of 
> re-dispatch and simply would be awfully expensive (you'd have to do full 
> program compilation to have any hope of decent code).

Re-dispatch is a bad idea anyway.

Yes, for untagged classes the conversions from the specific type to a class
and backwards are no more for free. But these types are meant to be
copyable anyway.

> The only alternative would be to totally ban implementation inheritance on 
> such types, but as implementation inheritance is 10 times more useful than 
> interface inheritance, it would make the construct 95% useless.

Huh, and you tell me that type cloning is useless? Cloning is all about
implementation inheritance.

For copyable objects implementation inheritance is much less interesting
than for by-reference types. Operations (especially cross operations) need
to be re-implemented anyway, at least for performance reasons. Few other
operations are [conversion ->] inherited body [-> conversion].

>> Making it regular is a simplification.
> 
> This isn't regular. All numeric types are currently members of a single 
> hierarchy,

It is not a single hierarchy. It is a forest of similar hierarchies. They
are similar just because they were constructed by the compiler rather than
by the programmer. It is nominal vs. structured. Same structure does not
imply equality, at least, it is meant to be so in Ada.

> and in practice, the vast majority of tagged types are members of 
> two hierarchies (controlled and limited controlled).

So what? This is equivalent to say that a type can be either copyable or
else not. Yes, "copyable" is an interface. There is a countable infinity of
other interfaces a type may implement. Which is why multiple inheritance is
so important.

But even if two types implement the same interface, e.g. can be copied,
that by no means should automatically imply that these types must belong to
the same hierarchy. This decision is up to the programmer.

Type cloning is a valuable mechanism to insulate type hierarchies against
each other.

Consider a container type defined for Copyable'Class. How do you prevent
mixing apples and oranges in there? Creating two new container types for
copyable apples and copyable oranges? But they are still the same
hierarchy. You need some fundamental operation which tells that a type
breaks off the hierarchy.

> More hierarchies don't buy anything (you can always move your 'Classes 
> around in the hierarchy to get subsets).

They buy safety through type checks.

>>>>>      overriding
>>>>>      procedure Op (A : in out Der; B : in Der);
>>>>
>>>> This is not an overriding since the mode is different.
>>>
>>> It *is* an overriding in Ada 83, and it still is in Ada 2012. I agree that
>>> it should not have been, but that is irrelevant because we're stuck with 
>>> it.
>>
>> Only when Der is derived using Ada 83 construct. Int'Class will be built
>> using "extension."
> 
> No way; derived types currently form a hierarchy (that's why you can 
> interconvert them); changing that would require fundamentally changing the 
> Ada model of hierarchies.

To me it is a wording issue not a real problem.

If you want a theoretic POV, no problem, both notions are fully compatible
with each other, it is one in a more general model:

Ada 83 hierarchy is a class of equivalence. Types from the hierarchy are
equal in the sense that they can be used interchangeable in the operations.
Each type is both a sub- and supertype of another (in non-Ada sense). The
graph of types is undirected.

Ada 95 tagged hierarchies are rather directed. A tagged type is only a
subtype (in non-Ada sense) of another tagged type in the hierarchy.

Untagged class would be an ability to have directed hierarchies of scalar
types and arrays. Why there should be none?

Conversely, ad-hoc supertypes would allow building Ada 83 equivalent types
with all types including tagged. You would derive a new type [=subtype] and
simultaneously declare it a supertype. This will effectively become a type
you can use interchangeably with the parent type [and get some ambiguities,
surely].

> The issue today is that you can't name those 
> hierarchies, that's what untagged 'Class would allow.

Name it a "taxonomy" then.

>>>>>      Obj : Int'Class := Der'(1);
>>>>>      Op (A => 1, B => Obj); -- Legal??
>>>>
>>>> MD is not fully implemented in Ada, but anyway, presuming that Op is a
>>>> multi-method, that the mode is "in" and that 1 is Universal_Integer (is
>>>> it?), the above is illegal because Op is not a method of
>>>> Universal_Integer'Class. You would have to write it as:
>>>>
>>>>   Op (A => Der'(1), B => Obj);  -- Same tags
>>>>   Op (A => Int'(1), B => Obj);  -- Different tags, Constraint_Error
>>>
>>> This seems wrong; an integer literal usually gets its type from context.
>>> It's only a value of type Universal_Integer if there is no type given from
>>> context (as in a type conversion or number declaration). I was presuming
>>> that integer literals act as tag-indeterminate functions (the most sensible
>>> model; if you have constants for a tagged type you usually would model them
>>> as tag-indeterminate functions - for instance, the constants Zero and One in
>>> a universal arithmetic package), you don't need multiple dispatch: the Ada
>>> dispatching rules simply calls the correct version of the function for the
>>> tag of the object. And that's what we would want to happen for integer
>>> literals (that's the closest analogy to what happens for existing
>>> expressions).
>>
>> This is one of possible interpretations of Ada semantics. You consider
>> literals primitive operations, e.g.
>>
>>   function "1" return Int;
>>
>> In Ada 95 such function has to be overridden, when Der extends Int.
>> However, if the representation is inherited and not changed, the rule 
>> could be that the compiler silently overrides all literals:
>>
>>   overriding function "1" return Der;
>>
>> In this case you will have 1 overloaded. Op will become ambiguous.
> 
> Yes, this is how Ada literals work today. This isn't how its described (it's 
> an implicit conversion rather than overloading) but the effect is the same.
> 
>> The alternative with different types can be discarded using some 
>> preference rules, e.g. domination, and thus ambiguity resolved.
> 
> Preference rules cause Beaujolias effects, and almost never can be 
> tolerated.

The idea that you can have an object of partially visible type was likely
wrong. So the separation of "with" and "use" was an mistake too. The
language should rather prevent declarations which are doomed to cause
ambiguities later.

> As soon as user-defined things are involved, preference rules simply don't 
> work.

Some rules are clearly needed to choose between:

   function "&" (Left : String; Right : Wide_String) return Wide_String;
   function "&" (Left : String; Right : Wide_String) return String;

The problem is not Ada design, but the nature of multi-methods with cross
operations enabled. The programmer should be allowed to declare some
signatures as equivalent, meaning: the compiler is free to use any without
reporting ambiguity.

The principle is always same, if you cannot decide it, leave to choice to
the programmer.

> The problem being that adding 
> or removing a single declaration can silently change the meaning of an 
> expression without causing an error. This is considered intolerable.)

Not always. It is OK with overriding.

My take on this that the language should prevent situations when you have
an object with some of its operations invisible, especially, when these
operations override the same primitive operation. I think this should be
possible to do while keeping it backward compatible, because standard types
are always visible anyway.

> My contention remains: if you are going to allow user 
> "Handle.all", then you need to expose the type of Handle.all. If you don't 
> need to allow that, then you are not going to use 4.1.5 at all. So I fail to 
> see your concern.

I don't need Handle.all, but I do need Handle.Foo meaning Handle.all.Foo.
Publicly it is an opaque by-copy type, privately it is an access type.

> Compiler checks are impossible for these things.

Why so? How is it different from in-mode of an argument. The compiler
routinely checks that you never update it.

> Unless you want to drive 
> yourself nuts with OOP baloney - and it's never going to be possible to do 
> these sorts of checks with type checking.

I don't understand why it has to be impossible to have:

   type File is ...;

   type Read_File is new File ...;
   prcodure Read (X : in out File; Data : out Stream_Element_Array);

   type Write_File is new File ...;
   procedure Write (X : in out File; Data : Stream_Element_Array);

   type Readwrite_File is new Read_File and Write_File ...;

with concrete types, but well possible with interfaces.

The nature of the check that the operation Write is not applied to
Read_File is exactly same in both cases.

It is not about checking, especially because the above construct is still
possible to get through generics. It is just a stupid limitation motivated
by urban legends mindlessly repeated through (using you wording) OO-baloney
texts.

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



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

* Re: Is this expected behavior or not
  2013-03-29 12:26                                                                                         ` Dmitry A. Kazakov
@ 2013-03-30  0:49                                                                                           ` Randy Brukardt
  2013-03-30  2:55                                                                                             ` Shark8
  2013-03-30  9:20                                                                                             ` Is this expected behavior or not Dmitry A. Kazakov
  0 siblings, 2 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-03-30  0:49 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:byacn0wck9qt$.norrlukaw80l$.dlg@40tude.net...
> On Thu, 28 Mar 2013 16:55:34 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:cqf0yy6q930$.1sdzw45bc0c1w.dlg@40tude.net...
>
>>> These are two data types, string and slice. Are you treating slice as an
>>> Ada-subtype of string? I consider slice a member of same class as 
>>> string,
>>> yet a distinct type (in Ada sense). This is like 4.1.5, but in the same
>>> type hierarchy.
>>
>> I thought you might do that, but then you're going to have problems of
>> compatibility (Ada currently considers them the same type). An operation
>> like "&" cannot not allow mixed string operands (if you do allow that, 
>> you
>> make string literals ambiguous).
>
> Right, if strings form a hierarchy, then "&" must be primitive and a
> multi-method. There is no alternative to that. Even if you are going to 
> add
> a completely new set of string types without slices you still will have
> this problem:
>
>   declare
>        X : New_String_Type;
>        Y : A_Descendant_Of;
>    begin
>        ... X & Y ...;  -- Is this legal? Does it raise Constraint_Error?
>
> The answers must be yes, no. And for this "&" must be a multi-method with
> all combinations of argument and the result types defined. Making some of
> them class-wide could reduce the number of combinations. And it will be
> ambiguous with literals and other overloaded operations returning string
> objects.

Well, actually, the answer is "no, irrelevant" as it is for the existing Ada 
types. You can always use an explicit type conversion if you need these to 
match. If each type effectively has its own literals, then this works 
perfectly. Mixing types is precisely the sort of thing you don't want to do 
in a strong typing environment.

I think this problem illustrates why the schemes you are thinking of will 
never be used -- they just add far too much complexity to the language. 
Maybe the 10000 foot view is simpler, but the complexity under the hood 
would be extremely difficult to implement.

>>>> Nobody wants "type cloning".
>>>
>>> It is a very useful building block to me. Anyway it is Ada 83 legacy.
>>
>> Ada 83 derived types are virtually useless, and no one understood how 
>> they
>> worked.
>
> What would you do if you need a new type with same properties. Copy-paste?

Make a new declaration, using constants for the properties. But the real 
answer is that this never happens, so it's a bogus concern. If the 
properties are truly the same, it's hardly likely that the type is the same. 
After all, the maximum number of Apples and Oranges is unlikely to be the 
same (the physical properties differ).

> Example:
>
>   type Position is <some positive number>;
>   type Key is some <some positive number>;
>   type Container is ...;
>
> How do you prevent Position and Key mixed in Container operations if they
> belong to same hierarchy?

If the container operations take parameters of type Key, then you can only 
pass a Position to such a parameter if you use an explicit conversion. 
That's how it works in Ada today - there's no automatic conversion between 
different specific types. If you have Root_Integer'Class parameters, then 
you made a choice to have weak typing, so there is no problem.

I think you're overthinking this...

 ...
> The model of Ada 95 tagged types provides a class with shared
> representations. This need to be augmented for the case when
> representations has to be different. Note that this was partially done 
> when
> Java interfaces were added in Ada 2005. Java interface is a type without
> any representation, so there is nothing to inherit from, except for a slot
> for the type tag. Drop that slot, and you will have a workable model for
> building classes of scalar types and arrays.

I don't know how one could implement "interfaces" without a tag. And there 
is no requirement in Ada that the representations of the tag be the same 
(although an implementation can impose one since there is no requirements 
about supporting tag positions).

>>> We also need "extension" that drops parent's representation altogether.
>>> E.g. something like:
>>>
>>>   type Character is new Unsigned_8 -- or enumeration, whatever
>>>      and Wide_Wide_Character'Interface;
>>>
>>> Character is member of Wide_Wide_Character'Class with a representation
>>> different from Wide_Wide_Character.
>>
>> I don't think that would work semantically, at least in the 'Class case.
>> Unless you expect every operation down to assigning individual components 
>> to
>> be dispatching, even in primitive routines defined for a specific type.
>
> Exactly! I want all that mess to become orderly defined primitive
> operations. This also includes attributes and aspects. There should be no
> special cases like T'Read, ":=" etc. There should be no magic and strange
> stuff like attributes, slices, ranges, aspects infesting the language, 
> only
> objects and operations.

You miss my point: the effect is to make *every* operation in *every* 
subprogram -- including specific ones -- dispatching -- which would be way 
too expensive in practice (no optimization would be possible).

>> That's because you can't copy all tagged types (we have to have limited
>> types), and thus calling a parent operation would have to assume that
>> extensions have a different representation. That would both have problems 
>> of
>> re-dispatch and simply would be awfully expensive (you'd have to do full
>> program compilation to have any hope of decent code).
>
> Re-dispatch is a bad idea anyway.
>
> Yes, for untagged classes the conversions from the specific type to a 
> class
> and backwards are no more for free. But these types are meant to be
> copyable anyway.

You are still misunderstanding. You'd *have* to have redispatch because the 
only way to implement inheritance would be to make all operations (even 
those very low-level ones) dispatching in *all* instances. There could be no 
statically bound operations.

>> The only alternative would be to totally ban implementation inheritance 
>> on
>> such types, but as implementation inheritance is 10 times more useful 
>> than
>> interface inheritance, it would make the construct 95% useless.
>
> Huh, and you tell me that type cloning is useless? Cloning is all about
> implementation inheritance.

The only useful inheritance is implementation inheritance, but it requires 
all of the types to be in the same hierarchy so that they can be 
interconvertable. (That doesn't necessarily mean *cheaply* 
interconvertable.) Interfaces are useful only in a very small % of cases, 
and that is such a small % that I wouldn't bother at all (certainly not more 
than Ada 95 abstract types).

> For copyable objects implementation inheritance is much less interesting
> than for by-reference types. Operations (especially cross operations) need
> to be re-implemented anyway, at least for performance reasons. Few other
> operations are [conversion ->] inherited body [-> conversion].

Not all objects that have different representations are copyable. (Consider 
an array of some_task'class). Whatever solution one has for untagged types 
has to be able to deal with uncopyable objects with different 
representations.

But banning implementation inheritance makes the whole thing useless IMHO, 
and supporting it is too expensive. It really kills the entire idea.

>>> Making it regular is a simplification.
>>
>> This isn't regular. All numeric types are currently members of a single
>> hierarchy,
>
> It is not a single hierarchy. It is a forest of similar hierarchies. They
> are similar just because they were constructed by the compiler rather than
> by the programmer. It is nominal vs. structured. Same structure does not
> imply equality, at least, it is meant to be so in Ada.

No, you need to read the RM again. All integer types are effectively derived 
from Universal_Integer, and all of the rest are derived from Universal_Real. 
There are only two hierachies. You're just not allowed to name them, which 
is limiting in various ways (especially as you can use 'Pos to force 
run-time operations to occur for Universal_Integer).

>> and in practice, the vast majority of tagged types are members of
>> two hierarchies (controlled and limited controlled).
>
> So what? This is equivalent to say that a type can be either copyable or
> else not. Yes, "copyable" is an interface. There is a countable infinity 
> of
> other interfaces a type may implement. Which is why multiple inheritance 
> is
> so important.

You mean why it is so useless. If you break down every possible property of 
a type as an interface, you'll end up with a very expensive complex 
structure. The only way I know of to implement multiple inheritance is with 
a linked-list of tags, which isn't too bad when only a few interfaces are 
involved. But once you get the dozens you're talking about, it's going to 
cause a very significant overhead.

> But even if two types implement the same interface, e.g. can be copied,
> that by no means should automatically imply that these types must belong 
> to
> the same hierarchy. This decision is up to the programmer.

I suspect that *all* types should belong to the same hierarchy, if you are 
going this OOP route. Because you need operations that work on every object, 
copyable or not. Remember, there are no type conversions between types in 
different hierarchies.

> Type cloning is a valuable mechanism to insulate type hierarchies against
> each other.
>
> Consider a container type defined for Copyable'Class. How do you prevent
> mixing apples and oranges in there? Creating two new container types for
> copyable apples and copyable oranges?

Of course you have separate containers for each kind of thing that they 
contain. When you define a container for Copyable'Class, you are allowing 
anything non-limited in that container -- you've specifically decided not to 
enforce any sort of checking on the contents.

> But they are still the same
> hierarchy. You need some fundamental operation which tells that a type
> breaks off the hierarchy.

Yes, of course all containers ought to be members of the same hierarchy. How 
else would you create generic algorithms? It's unfortunate that Ada doesn't 
allow this because the element type makes it impossible. No idea how to work 
around that.

>> More hierarchies don't buy anything (you can always move your 'Classes
>> around in the hierarchy to get subsets).
>
> They buy safety through type checks.

Since *every* type in a hierarchy is different and cannot be mixed with any 
other type unless you explicitly request it (via declaring something to be 
class-wide), you are gaining absolutely nothing by added hierarchies.

...
>> The issue today is that you can't name those
>> hierarchies, that's what untagged 'Class would allow.
>
> Name it a "taxonomy" then.

I see, you're wasting my time again by changing the terminology on the fly. 
I should know better than to discuss anything substantive with you. My 
mistake.

 ...
>> Preference rules cause Beaujolias effects, and almost never can be
>> tolerated.
>
> The idea that you can have an object of partially visible type was likely
> wrong. So the separation of "with" and "use" was an mistake too. The
> language should rather prevent declarations which are doomed to cause
> ambiguities later.

No one has ever figured out how to do that, and in any case, it would be 
incompatible with Ada as it stands. We can't even do simple things like make 
objects overloadable because of compatibility concerns -- changing the 
visibility model is a non-starter.

>> As soon as user-defined things are involved, preference rules simply 
>> don't
>> work.
>
> Some rules are clearly needed to choose between:
>
>   function "&" (Left : String; Right : Wide_String) return Wide_String;
>   function "&" (Left : String; Right : Wide_String) return String;

There are no such operations predefined in Ada, and that's because you 
*can't* chose between them. You can of course declare them yourself (that's 
essentially what happens in Ada.Strings.Unbounded), but the net effect is 
that you then cannot use literals with such a type. Ada does not attempt to 
prevent you from shooting yourself in the head. :-)

>> The problem being that adding
>> or removing a single declaration can silently change the meaning of an
>> expression without causing an error. This is considered intolerable.)
>
> Not always. It is OK with overriding.

That isn't quite the same thing, because the declaration in question is 
replacing one, not adding or removing one. And of course in a good system 
they'll also have the same preconditions and postconditions, meaning that 
the changed operation would have very similar semantics.

The cases I'm thinking about have to do with ordinary object declarations 
being added or removed elsewhere in the program. Changing the object used 
silently is intolerable.

Personally, however, I've concluded that the OOP cases are also very 
dangerous. Maybe not quite to the level of "intolerable", but pretty close. 
That's the curse of OOP: not being able to figure out what routine is being 
called (and especially why the *wrong* routine is being called).

> My take on this that the language should prevent situations when you have
> an object with some of its operations invisible, especially, when these
> operations override the same primitive operation. I think this should be
> possible to do while keeping it backward compatible, because standard 
> types
> are always visible anyway.

Huh? This is very common with private types. With interfaces, we enforced 
such a rule and it is rather limiting.

Claw uses hidden operations on window objects to keep the mechanisms of the 
message loop hidden away. Otherwise, we'd have no way to ensure that our 
objects are getting the messages as intended, and it would be impossible to 
make anything work reliably. These routines have to be dispatching, as the 
responses to different messages obviously depend on the kind of object they 
are associated with. So they have to be inherited and overriddable, but not 
changable by clients (who might be doing their own overriding of public 
operations for their own purposes).

In general, designers of good libraries need to be able to hide the 
mechanics of the implementation from clients (both for understandability and 
to prevent people from screwing them up). Without being able to hide 
operations, there is no hope of that.

>> My contention remains: if you are going to allow user
>> "Handle.all", then you need to expose the type of Handle.all. If you 
>> don't
>> need to allow that, then you are not going to use 4.1.5 at all. So I fail 
>> to
>> see your concern.
>
> I don't need Handle.all, but I do need Handle.Foo meaning Handle.all.Foo.
> Publicly it is an opaque by-copy type, privately it is an access type.

In this case, you're probably not using 4.1.5, because it is only about .all 
(and writing into .all specifically).

If you are using 4.1.5 (to allow writing into Foo), you're exposing an 
access to the type of Foo, not to the file type.

>> Unless you want to drive
>> yourself nuts with OOP baloney - and it's never going to be possible to 
>> do
>> these sorts of checks with type checking.
>
> I don't understand why it has to be impossible to have:
>
>   type File is ...;
>
>   type Read_File is new File ...;
>   prcodure Read (X : in out File; Data : out Stream_Element_Array);
>
>   type Write_File is new File ...;
>   procedure Write (X : in out File; Data : Stream_Element_Array);
>
>   type Readwrite_File is new Read_File and Write_File ...;
>
> with concrete types, but well possible with interfaces.
>
> The nature of the check that the operation Write is not applied to
> Read_File is exactly same in both cases.

You can do this sort of thing in exceedingly simple cases. But it simply 
gets too complex the more properties that you try to decompose on. And every 
such property is making all of your dispatching calls slower and slower.

Moreover, most interesting properties are not binary like the file mode. 
They tend to depend on the *values* of parameters, and often on combinations 
of values. It just is too complex to do.

> It is not about checking, especially because the above construct is still
> possible to get through generics. It is just a stupid limitation motivated
> by urban legends mindlessly repeated through (using you wording) 
> OO-baloney
> texts.

Implementability is hardly an "urban legend". If the resulting code is too 
slow to use, then it's pretty silly to structure it that way, even if it is 
theoretically possible.

                                                   Randy.





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

* Re: Is this expected behavior or not
  2013-03-30  0:49                                                                                           ` Randy Brukardt
@ 2013-03-30  2:55                                                                                             ` Shark8
  2013-04-01 23:43                                                                                               ` Messaging question [was: Is this expected behavior or not] Randy Brukardt
  2013-03-30  9:20                                                                                             ` Is this expected behavior or not Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Shark8 @ 2013-03-30  2:55 UTC (permalink / raw)


On Friday, March 29, 2013 6:49:25 PM UTC-6, Randy Brukardt wrote:
> 
> 
> Claw uses hidden operations on window objects to keep the mechanisms of the 
> message loop hidden away.

Very tangentially on this; what do you see would be the consequence of a system using a loop over a select [for messaging] -- or would it be any different?

I'm really fuzzy on my low-level windows programming and, after reading this ( http://forums.codeguru.com/showthread.php?449338-Windows-message-loop-efficiency ), I found myself wondering; since you wrote CLAW I thought I'd ask.



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

* Re: Is this expected behavior or not
  2013-03-30  0:49                                                                                           ` Randy Brukardt
  2013-03-30  2:55                                                                                             ` Shark8
@ 2013-03-30  9:20                                                                                             ` Dmitry A. Kazakov
  2013-04-02  0:40                                                                                               ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-03-30  9:20 UTC (permalink / raw)


On Fri, 29 Mar 2013 19:49:25 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:byacn0wck9qt$.norrlukaw80l$.dlg@40tude.net...
>> On Thu, 28 Mar 2013 16:55:34 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:cqf0yy6q930$.1sdzw45bc0c1w.dlg@40tude.net...
>>
>>>> These are two data types, string and slice. Are you treating slice as an
>>>> Ada-subtype of string? I consider slice a member of same class as string,
>>>> yet a distinct type (in Ada sense). This is like 4.1.5, but in the same
>>>> type hierarchy.
>>>
>>> I thought you might do that, but then you're going to have problems of
>>> compatibility (Ada currently considers them the same type). An operation
>>> like "&" cannot not allow mixed string operands (if you do allow that, 
>>> you make string literals ambiguous).
>>
>> Right, if strings form a hierarchy, then "&" must be primitive and a
>> multi-method. There is no alternative to that. Even if you are going to 
>> add a completely new set of string types without slices you still will have
>> this problem:
>>
>>   declare
>>        X : New_String_Type;
>>        Y : A_Descendant_Of;
>>    begin
>>        ... X & Y ...;  -- Is this legal? Does it raise Constraint_Error?
>>
>> The answers must be yes, no. And for this "&" must be a multi-method with
>> all combinations of argument and the result types defined. Making some of
>> them class-wide could reduce the number of combinations. And it will be
>> ambiguous with literals and other overloaded operations returning string
>> objects.
> 
> Well, actually, the answer is "no, irrelevant" as it is for the existing Ada 
> types. You can always use an explicit type conversion if you need these to 
> match. If each type effectively has its own literals, then this works 
> perfectly. Mixing types is precisely the sort of thing you don't want to do 
> in a strong typing environment.
> 
> I think this problem illustrates why the schemes you are thinking of will 
> never be used -- they just add far too much complexity to the language.

The point is that whether you create a totally new string hierarchy or
create one for already existing string types, you will have the issue with
"&" (and any other operation with more than one argument/result of string
type). That is *independent* on whatever Ada did or not before. It is in
the nature of a multi-method, which "&" is. If you want a hierarchy of
strings you *must* face this problem.

>>>>> Nobody wants "type cloning".
>>>>
>>>> It is a very useful building block to me. Anyway it is Ada 83 legacy.
>>>
>>> Ada 83 derived types are virtually useless, and no one understood how 
>>> they worked.
>>
>> What would you do if you need a new type with same properties. Copy-paste?
> 
> Make a new declaration, using constants for the properties.

Properties are operations here.

> But the real 
> answer is that this never happens, so it's a bogus concern. If the 
> properties are truly the same, it's hardly likely that the type is the same.

   type Velocity is new Float;
 
>> Example:
>>
>>   type Position is <some positive number>;
>>   type Key is some <some positive number>;
>>   type Container is ...;
>>
>> How do you prevent Position and Key mixed in Container operations if they
>> belong to same hierarchy?
> 
> If the container operations take parameters of type Key, then you can only 
> pass a Position to such a parameter if you use an explicit conversion.

Position and Key are just same type according to you. You said you don't
need independent hierarchies of any types, which should include numbers.
 
>> The model of Ada 95 tagged types provides a class with shared
>> representations. This need to be augmented for the case when
>> representations has to be different. Note that this was partially done when
>> Java interfaces were added in Ada 2005. Java interface is a type without
>> any representation, so there is nothing to inherit from, except for a slot
>> for the type tag. Drop that slot, and you will have a workable model for
>> building classes of scalar types and arrays.
> 
> I don't know how one could implement "interfaces" without a tag.

You have the tag in the representation of untagged'Class. You don't have it
in the representation of untagged.

>>>> We also need "extension" that drops parent's representation altogether.
>>>> E.g. something like:
>>>>
>>>>   type Character is new Unsigned_8 -- or enumeration, whatever
>>>>      and Wide_Wide_Character'Interface;
>>>>
>>>> Character is member of Wide_Wide_Character'Class with a representation
>>>> different from Wide_Wide_Character.
>>>
>>> I don't think that would work semantically, at least in the 'Class case.
>>> Unless you expect every operation down to assigning individual components 
>>> to be dispatching, even in primitive routines defined for a specific type.
>>
>> Exactly! I want all that mess to become orderly defined primitive
>> operations. This also includes attributes and aspects. There should be no
>> special cases like T'Read, ":=" etc. There should be no magic and strange
>> stuff like attributes, slices, ranges, aspects infesting the language, 
>> only objects and operations.
> 
> You miss my point: the effect is to make *every* operation in *every* 
> subprogram -- including specific ones -- dispatching -- which would be way 
> too expensive in practice (no optimization would be possible).

Then it is wrong what you wrote. There will be no dispatch on specific
types.

(I don't understand why you think that dispatching on specific types is
necessary)

> You are still misunderstanding. You'd *have* to have redispatch because the 
> only way to implement inheritance would be to make all operations (even 
> those very low-level ones) dispatching in *all* instances. There could be no 
> statically bound operations.

Yes, I still do not understand what has re-dispatch to do with inheritance
(of what?)

The representation is NOT inherited

Primitive operations (AKA, interface) are inherited in the way standard to
tagged types. That is, a NEW operation is declared with the same name and
the profile where the parent type is replaced by the descendant type.

The way its body is generated out of old body with parent type converted to
the descendant type in- and/or out.

How this requires re-dispatch?

>> For copyable objects implementation inheritance is much less interesting
>> than for by-reference types. Operations (especially cross operations) need
>> to be re-implemented anyway, at least for performance reasons. Few other
>> operations are [conversion ->] inherited body [-> conversion].
> 
> Not all objects that have different representations are copyable. (Consider 
> an array of some_task'class). Whatever solution one has for untagged types 
> has to be able to deal with uncopyable objects with different 
> representations.
> 
> But banning implementation inheritance makes the whole thing useless IMHO, 
> and supporting it is too expensive.

I don't ban inheritance of the representation. I want to be able not to do
it when I don't need it, e.g. for character and string types.
 
> It really kills the entire idea.

No, IF String inherited the representation of Wide_Wide_String, THAT would
kill the idea.

The whole idea is not to inherit irrelevant representations!

>>>> Making it regular is a simplification.
>>>
>>> This isn't regular. All numeric types are currently members of a single
>>> hierarchy,
>>
>> It is not a single hierarchy. It is a forest of similar hierarchies. They
>> are similar just because they were constructed by the compiler rather than
>> by the programmer. It is nominal vs. structured. Same structure does not
>> imply equality, at least, it is meant to be so in Ada.
> 
> No, you need to read the RM again. All integer types are effectively derived 
> from Universal_Integer, and all of the rest are derived from Universal_Real. 
> There are only two hierachies.

OK, this again becomes a scholastic discussion we need not to go into.

The bottom line is, I regard Ada 83 construct "type S is new T;" as very
useful, and wished it be valid with all specific types without silly
exceptions Ada 95 made for tagged types.

>>> and in practice, the vast majority of tagged types are members of
>>> two hierarchies (controlled and limited controlled).
>>
>> So what? This is equivalent to say that a type can be either copyable or
>> else not. Yes, "copyable" is an interface. There is a countable infinity of
>> other interfaces a type may implement. Which is why multiple inheritance 
>> is so important.
> 
> You mean why it is so useless. If you break down every possible property of 
> a type as an interface, you'll end up with a very expensive complex 
> structure.

It is how it is. A number is a field, additive group, weak ordered and so
on... A good language shall support programmer in expressing concepts of
the problem domain.

> The only way I know of to implement multiple inheritance is with 
> a linked-list of tags, which isn't too bad when only a few interfaces are 
> involved. But once you get the dozens you're talking about, it's going to 
> cause a very significant overhead.

There is no overhead on any existing Ada program.

>> But even if two types implement the same interface, e.g. can be copied,
>> that by no means should automatically imply that these types must belong 
>> to the same hierarchy. This decision is up to the programmer.
> 
> I suspect that *all* types should belong to the same hierarchy, if you are 
> going this OOP route.

To make yet another bogus OOPL out of Ada?

> Because you need operations that work on every object, 
> copyable or not. Remember, there are no type conversions between types in 
> different hierarchies.

And, this is what different hierarchies are for.

>> Type cloning is a valuable mechanism to insulate type hierarchies against
>> each other.
>>
>> Consider a container type defined for Copyable'Class. How do you prevent
>> mixing apples and oranges in there? Creating two new container types for
>> copyable apples and copyable oranges?
> 
> Of course you have separate containers for each kind of thing that they 
> contain. When you define a container for Copyable'Class, you are allowing 
> anything non-limited in that container -- you've specifically decided not to 
> enforce any sort of checking on the contents.

And cloning is there to enforce checking.

>> But they are still the same
>> hierarchy. You need some fundamental operation which tells that a type
>> breaks off the hierarchy.
> 
> Yes, of course all containers ought to be members of the same hierarchy. How 
> else would you create generic algorithms?

Easily. Cloning borrows all operations. Define algorithm on the original
type. Then clone it. Done!

>>> As soon as user-defined things are involved, preference rules simply 
>>> don't work.
>>
>> Some rules are clearly needed to choose between:
>>
>>   function "&" (Left : String; Right : Wide_String) return Wide_String;
>>   function "&" (Left : String; Right : Wide_String) return String;
> 
> There are no such operations predefined in Ada, and that's because you 
> *can't* chose between them. You can of course declare them yourself (that's 
> essentially what happens in Ada.Strings.Unbounded), but the net effect is 
> that you then cannot use literals with such a type. Ada does not attempt to 
> prevent you from shooting yourself in the head. :-)

Are you seriously going to propose a string class without "&"?

>> My take on this that the language should prevent situations when you have
>> an object with some of its operations invisible, especially, when these
>> operations override the same primitive operation. I think this should be
>> possible to do while keeping it backward compatible, because standard 
>> types are always visible anyway.
> 
> Huh? This is very common with private types. With interfaces, we enforced 
> such a rule and it is rather limiting.
> 
> Claw uses hidden operations on window objects to keep the mechanisms of the 
> message loop hidden away.

I didn't meant that. Whether public or private an operation on the object
should be visible if you would see it otherwise, e.g. through use-clause.

>>> My contention remains: if you are going to allow user
>>> "Handle.all", then you need to expose the type of Handle.all. If you don't
>>> need to allow that, then you are not going to use 4.1.5 at all. So I fail 
>>> to see your concern.
>>
>> I don't need Handle.all, but I do need Handle.Foo meaning Handle.all.Foo.
>> Publicly it is an opaque by-copy type, privately it is an access type.
> 
> In this case, you're probably not using 4.1.5, because it is only about .all 
> (and writing into .all specifically).

Yes, 4.1.5 is a hack for one specific case.

>>> Unless you want to drive
>>> yourself nuts with OOP baloney - and it's never going to be possible to 
>>> do these sorts of checks with type checking.
>>
>> I don't understand why it has to be impossible to have:
>>
>>   type File is ...;
>>
>>   type Read_File is new File ...;
>>   prcodure Read (X : in out File; Data : out Stream_Element_Array);
>>
>>   type Write_File is new File ...;
>>   procedure Write (X : in out File; Data : Stream_Element_Array);
>>
>>   type Readwrite_File is new Read_File and Write_File ...;
>>
>> with concrete types, but well possible with interfaces.
>>
>> The nature of the check that the operation Write is not applied to
>> Read_File is exactly same in both cases.
> 
> You can do this sort of thing in exceedingly simple cases. But it simply 
> gets too complex the more properties that you try to decompose on. And every 
> such property is making all of your dispatching calls slower and slower.

I would gladly buy that in exchange for how it is now: 100+ generic
packages, 1000+ instances, 4 hours compilation time, no way to compile on a
32-bit host.

> Moreover, most interesting properties are not binary like the file mode. 
> They tend to depend on the *values* of parameters, and often on combinations 
> of values. It just is too complex to do.

It is becomes increasingly expensive not to do it. There is a language
damage as well inflicted by all hacks of Ada 2005-2012. Further hacks are
in the pipe line, I guess.

>> It is not about checking, especially because the above construct is still
>> possible to get through generics. It is just a stupid limitation motivated
>> by urban legends mindlessly repeated through (using you wording) 
>> OO-baloney
>> texts.
> 
> Implementability is hardly an "urban legend". If the resulting code is too 
> slow to use

I saw no significant overhead in C++ programs, which has full MI from the
start.

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



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

* Re: Messaging question [was: Is this expected behavior or not]
  2013-03-30  2:55                                                                                             ` Shark8
@ 2013-04-01 23:43                                                                                               ` Randy Brukardt
  0 siblings, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-04-01 23:43 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:09f2e5f7-84fe-419b-b27d-207e697c8e46@googlegroups.com...
> On Friday, March 29, 2013 6:49:25 PM UTC-6, Randy Brukardt wrote:
>>
>>
>> Claw uses hidden operations on window objects to keep the mechanisms of 
>> the
>> message loop hidden away.
>
> Very tangentially on this; what do you see would be the consequence of a 
> system
> using a loop over a select [for messaging] -- or would it be any 
> different?
>
> I'm really fuzzy on my low-level windows programming and, after reading 
> this
>( 
>http://forums.codeguru.com/showthread.php?449338-Windows-message-loop-efficiency ) 
>,
>I found myself wondering; since you wrote CLAW I thought I'd ask.

The reason we hid the loop had to do with correctness more than efficiency. 
When you explicitly allow fooling with all of that loop mechanism, it's 
impossible to build anything on top of it and have any hope that it works 
right, because you're relying on the client to use the object exactly the 
right way, or it won't work (nor will it give any indication of what you did 
wrong).

In any case, there is *always* a loop inside the application; the question 
in the thread mentioned above is how the loop is written. You get dozens of 
messages for typical actions in an Windows program; you need a loop to 
process them all. I believe we did our waiting at the Ada level, rather than 
the Windows level, because that prevented locking up the Windows 
program/thread while waiting for something to happen. We use Ada delays to 
release the CPU if we don't have anything to do (that way, the Ada runtime 
knows about the blocking and can schedule other work if appropriate). Again, 
performance had nothing to do with it, we didn't want to assume a particular 
Ada runtime model (that is, how tasks are mapped to threads). We tuned the 
performance after making these choices.

                                     Randy.





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

* Re: Is this expected behavior or not
  2013-03-30  9:20                                                                                             ` Is this expected behavior or not Dmitry A. Kazakov
@ 2013-04-02  0:40                                                                                               ` Randy Brukardt
  2013-04-02  8:44                                                                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-02  0:40 UTC (permalink / raw)



"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net...
....
> The point is that whether you create a totally new string hierarchy or
> create one for already existing string types, you will have the issue with
> "&" (and any other operation with more than one argument/result of string
> type). That is *independent* on whatever Ada did or not before. It is in
> the nature of a multi-method, which "&" is. If you want a hierarchy of
> strings you *must* face this problem.

No you don't. There are no language-defined multi-methods. String & String = 
String is not a multi-method. You, the user, can define such operations, of 
course, but then you have the deal with the consequences. Generally, it's 
best if you don't do that.

...
>> If the container operations take parameters of type Key, then you can 
>> only
>> pass a Position to such a parameter if you use an explicit conversion.
>
> Position and Key are just same type according to you. You said you don't
> need independent hierarchies of any types, which should include numbers.

You're not making any sense. We're talking about hierarchies of types; 
*everything* in such a hierarchy is a separate type. (Ada subtypes are 
completely independent of any type hierarchies, and completely irrelevant 
for this purpose.) There really is only one hierarchy of types per 
programming language; the only question is how much interoperation between 
different types is allowed. It's probably misleading to ever say that there 
is "more than one hierarchy of types" in a program (or programming 
language).

My guess is that you've redefined the meaning of hierarchy again, so please 
just forget it, there's no point in discussing this further. If you're 
unwilling to use Ada terminology on this Ada list, then we really have 
nothing to talk about.

>>> The model of Ada 95 tagged types provides a class with shared
>>> representations. This need to be augmented for the case when
>>> representations has to be different. Note that this was partially done 
>>> when
>>> Java interfaces were added in Ada 2005. Java interface is a type without
>>> any representation, so there is nothing to inherit from, except for a 
>>> slot
>>> for the type tag. Drop that slot, and you will have a workable model for
>>> building classes of scalar types and arrays.
>>
>> I don't know how one could implement "interfaces" without a tag.
>
> You have the tag in the representation of untagged'Class. You don't have 
> it
> in the representation of untagged.

Doesn't work, as I've previously explained. You have to be able to inherit 
implementation of operations, for all types. And there exist plenty of Ada 
types for which copying is not allowed. The only way to implement those is 
via some sort of dispatching, and the need poisons the possibility of 
omitting tags, even for "specific" operations.

You can of course adopt severely incompatible rules (can't inherit 
operations for derived limited types) or add complexity by making a new kind 
of derivation (you can't get rid of the old kind, so you're adding lots of 
new complexity without eliminating any old complexity). Neither sound 
appealing to me. For a new Ada-like language, the choices are different, but 
for Ada itself, it doesn't really work.

I've explained this several times already and I'm not bothering to do so 
again.


>>>>> We also nd "extension" that drops parent's representation altogether.
>>>>> E.g. something like:
>>>>>
>>>>>   type Character is new Unsigned_8 -- or enumeration, whatever
>>>>>      and Wide_Wide_Character'Interface;
...
>> You miss my point: the effect is to make *every* operation in *every*
>> subprogram -- including specific ones -- dispatching -- which would be 
>> way
>> too expensive in practice (no optimization would be possible).
>
> Then it is wrong what you wrote. There will be no dispatch on specific
> types.
>
> (I don't understand why you think that dispatching on specific types is
> necessary)

I've explained it previously and above again. You're welcome to disagree, 
but the only way to *prove* me wrong is to create a real proposal, in *Ada* 
terms, with proposed wording using *Ada* terminology, that does not have any 
significant incompatibilities. You've never made any attempt to address the 
real problems to this point, and I'm pretty certain that you can't.

...
>> You are still misunderstanding. You'd *have* to have redispatch because 
>> the
>> only way to implement inheritance would be to make all operations (even
>> those very low-level ones) dispatching in *all* instances. There could be 
>> no
>> statically bound operations.
>
> Yes, I still do not understand what has re-dispatch to do with inheritance
> (of what?)
>
> The representation is NOT inherited
>
> Primitive operations (AKA, interface) are inherited in the way standard to
> tagged types. That is, a NEW operation is declared with the same name and
> the profile where the parent type is replaced by the descendant type.
>
> The way its body is generated out of old body with parent type converted 
> to
> the descendant type in- and/or out.
>
> How this requires re-dispatch?

The type conversions are view conversions, and they never make copies. That 
forces the representation to be compatible. You could change that for 
by-copy types (although that would have run-time compatibility issues for 
controlled objects), but you can't change that for types that have no copy 
operation (like tasks and protected objects). So how to do you implement 
them? Array of task is an untagged type, too, and it certainly should be 
able to use 'Class.

...
> I don't ban inheritance of the representation. I want to be able not to do
> it when I don't need it, e.g. for character and string types.

But it's not that easy. If you have an array of tasks:

    type Foo (1 .. 10) of Some_Task with Component_Size => 32;

and you derive another array of tasks from it:

   type New_Foo is new Foo with Component_Size => 64;

This is legal, and you have different representations.

>> It really kills the entire idea.
>
> No, IF String inherited the representation of Wide_Wide_String, THAT would
> kill the idea.
>
> The whole idea is not to inherit irrelevant representations!

I don't see the problem here; if Root_String is an abstract tagged type, the 
various concrete types derived from it all have completely diifferent 
representations. It's the same as happens for controlled types: there is no 
requirement that the representation of different controlled types is the 
same.

This is standard stuff - if you don't want to inherit a representation, then 
don't, inherit from an abstract type (or interface, if you prefer) that has 
no representation. Don't try to get rid of an already existing 
representation, because that makes real trouble for inherited operations.

...
> The bottom line is, I regard Ada 83 construct "type S is new T;" as very
> useful, and wished it be valid with all specific types without silly
> exceptions Ada 95 made for tagged types.

Fair enough. I regard "type S is new T;" as a junk piece of syntax that was 
inherited from Ada 83, and should never be used. We completely disagree on 
this one, and there really is nothing worth talking about.

You previously asked about:

    type Velocity is new Float;

That would get you a repremand if you worked for me. You never, ever use the 
types in Standard (because they're not necessarily portable to other 
compilers). You derive types based on your actual application requirements:

   type Velocity is digits 5 range -1.0E+10 .. 1.0E+10;

And let the compiler pick the representation. Similarly, if you are matching 
hardware, you declare types that match that hardware (specify Size, 
Object_Size, etc.).

If you're writing true throw-away code, just use the types in Standard 
directly and forget the strong typing (it's throw-away, after all).

There are so few cases that don't fit in one of these that it doesn't pay to 
have the feature in the language. Especially if we can fix the "renaming of 
the contents of an instantiation" problem somehow.

...
>> The only way I know of to implement multiple inheritance is with
>> a linked-list of tags, which isn't too bad when only a few interfaces are
>> involved. But once you get the dozens you're talking about, it's going to
>> cause a very significant overhead.
>
> There is no overhead on any existing Ada program.

Only if the compiler-writer can implement many special cases in their code. 
I think this is unlikely; perhaps AdaCore has the resources to pull it off, 
but I doubt that any other vendor does. Janus/Ada tends to implement all 
types with the same code and optimize to better code, meaning the most 
general case is the typically the only thing that we implement. It wouldn't 
be possible to optimize that to anything remotely like the existing Ada 
code, certainly not with the resources we have. And we'd be going backwards 
at best - no thanks.

...
>> Because you need operations that work on every object,
>> copyable or not. Remember, there are no type conversions between types in
>> different hierarchies.
>
> And, this is what different hierarchies are for.

For what? To make it impossible to pass integers to Text_IO, or to use them 
to instantiation Text_IO? (If you can't convert, you can't instantiate or 
use 'Class either.) How is that going to help make Ada more regular??

...
> And cloning is there to enforce checking.

Huh? You get checking every time you make a new type, whether it is in the 
same hierarchy or a different one. The hierarchy defines what conversions 
are allowed (to/from 'Class, between related types). That's it. The type 
checking for specific types is exactly the same either way.

...
>>> But they are still the same
>>> hierarchy. You need some fundamental operation which tells that a type
>>> breaks off the hierarchy.
>>
>> Yes, of course all containers ought to be members of the same hierarchy. 
>> How
>> else would you create generic algorithms?
>
> Easily. Cloning borrows all operations. Define algorithm on the original
> type. Then clone it. Done!

But you have cloned nothing. Either you have a conversion to the original 
type, in which case they belong to the same hierarchy. Or you don't have a 
conversion, and then you can't inherit any implementations, because that 
involves conversions.

>>>> As soon as user-defined things are involved, preference rules simply
>>>> don't work.
>>>
>>> Some rules are clearly needed to choose between:
>>>
>>>   function "&" (Left : String; Right : Wide_String) return Wide_String;
>>>   function "&" (Left : String; Right : Wide_String) return String;
>>
>> There are no such operations predefined in Ada, and that's because you
>> *can't* chose between them. You can of course declare them yourself 
>> (that's
>> essentially what happens in Ada.Strings.Unbounded), but the net effect is
>> that you then cannot use literals with such a type. Ada does not attempt 
>> to
>> prevent you from shooting yourself in the head. :-)
>
> Are you seriously going to propose a string class without "&"?

A string class with a mixed & is nonsense. (I think the String & Character 
in Ada 83 was nonsense, but it's not a problem here.)

The only & is String & String = String, and so on for all types. For 
compatibility, we'd also have String & Element = String. Nothing else -- no 
mixed string types. You never need such types anyway, they just make 
understanding of an expression impossible.

>>> My take on this that the language should prevent situations when you 
>>> have
>>> an object with some of its operations invisible, especially, when these
>>> operations override the same primitive operation. I think this should be
>>> possible to do while keeping it backward compatible, because standard
>>> types are always visible anyway.
>>
>> Huh? This is very common with private types. With interfaces, we enforced
>> such a rule and it is rather limiting.
>>
>> Claw uses hidden operations on window objects to keep the mechanisms of 
>> the
>> message loop hidden away.
>
> I didn't meant that. Whether public or private an operation on the object
> should be visible if you would see it otherwise, e.g. through use-clause.

I think that's already the case. The problem is with "additional operations" 
that appear when you know more about a type, and that's completely related 
to private types and nesting. In my Ada-like language, I would ban that from 
happening, but it's 30 years too late for Ada in this way.

...
>> You can do this sort of thing in exceedingly simple cases. But it simply
>> gets too complex the more properties that you try to decompose on. And 
>> every
>> such property is making all of your dispatching calls slower and slower.
>
> I would gladly buy that in exchange for how it is now: 100+ generic
> packages, 1000+ instances, 4 hours compilation time, no way to compile on 
> a
> 32-bit host.

Fair enough; the problem is that you're in a very small minority. I know I 
would not accept that kind of slow-down in my code, especially if there was 
no corresponding benefit for me.

>> Moreover, most interesting properties are not binary like the file mode.
>> They tend to depend on the *values* of parameters, and often on 
>> combinations
>> of values. It just is too complex to do.
>
> It is becomes increasingly expensive not to do it. There is a language
> damage as well inflicted by all hacks of Ada 2005-2012. Further hacks are
> in the pipe line, I guess.

No idea, we haven't done much yet, private musings by me means little.

I think there would be an argument for the position that we're reaching the 
limit of what we can do sensibly to Ada, and that we might have to make a 
clean break at some point to get rid of all of the legacy garbage. But I 
suspect that there wouldn't be enough customers for that sort of 
incompatible change. (See all of the problems the Python people are having 
from when they did that.)

>>> It is not about checking, especially because the above construct is 
>>> still
>>> possible to get through generics. It is just a stupid limitation 
>>> motivated
>>> by urban legends mindlessly repeated through (using you wording)
>>> OO-baloney
>>> texts.
>>
>> Implementability is hardly an "urban legend". If the resulting code is 
>> too
>> slow to use
>
> I saw no significant overhead in C++ programs, which has full MI from the
> start.

C++ is free of some of the Ada 83 legacy that weighs us down. There's a 
reason that Ada never will allow redefining of ":=", for one example. (I'm 
also dubious of your actual assertion; you probably aren't looking in the 
right places. I certainly can believe that you aren't seeing that slow-down, 
perhaps other effects predominate. I know I would see it, but of course I 
can't say how significant it would be without actually benchmarking it --  
which isn't going to happen because I'm surely not implementing you're 
imaginative language.)

                                   Randy.





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

* Re: Is this expected behavior or not
  2013-04-02  0:40                                                                                               ` Randy Brukardt
@ 2013-04-02  8:44                                                                                                 ` Dmitry A. Kazakov
  2013-04-02 21:54                                                                                                   ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-02  8:44 UTC (permalink / raw)


On Mon, 1 Apr 2013 19:40:42 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net...
> ....
>> The point is that whether you create a totally new string hierarchy or
>> create one for already existing string types, you will have the issue with
>> "&" (and any other operation with more than one argument/result of string
>> type). That is *independent* on whatever Ada did or not before. It is in
>> the nature of a multi-method, which "&" is. If you want a hierarchy of
>> strings you *must* face this problem.
> 
> No you don't. There are no language-defined multi-methods. String & String = 
> String is not a multi-method.

Once String becomes member of a class it is. For the operation "&" there
exist only two possibilities, Either it is a primitive operation of the
class and so a multi-method, or else it is declared individually on each
member of the class in separate packages (somewhere after the freezing
point). The later variant is so silly that I don't even consider it.

> You, the user, can define such operations, of 
> course, but then you have the deal with the consequences. Generally, it's 
> best if you don't do that.

What is the use of a string type without operations? 

>>>> The model of Ada 95 tagged types provides a class with shared
>>>> representations. This need to be augmented for the case when
>>>> representations has to be different. Note that this was partially done when
>>>> Java interfaces were added in Ada 2005. Java interface is a type without
>>>> any representation, so there is nothing to inherit from, except for a slot
>>>> for the type tag. Drop that slot, and you will have a workable model for
>>>> building classes of scalar types and arrays.
>>>
>>> I don't know how one could implement "interfaces" without a tag.
>>
>> You have the tag in the representation of untagged'Class. You don't have 
>> it in the representation of untagged.
> 
> Doesn't work, as I've previously explained.

You said that it would not fit into Ada 83 derived types model. I answered
that it never considered within that model. The model to augment is Ada 95
tagged types.

> You have to be able to inherit 
> implementation of operations, for all types.

It is already not so. See Ada 95 abstract primitive operations and
operations dispatching in the result. They are NOT inherited. The
programmer is asked to override them, because the compiler has no idea how
to implement them.

> And there exist plenty of Ada 
> types for which copying is not allowed.

No problem. See above. All primitive operation will be inherited abstract
if the representation is not inherited and no [user-defined] conversion
defined (e.g. for a by-reference type).

> The only way to implement those is 
> via some sort of dispatching, and the need poisons the possibility of 
> omitting tags, even for "specific" operations.

I don't understand where you get this. The model is exactly the model of
tagged types, but without specific objects required to keep the tag. The
only thing it influences is view conversions between T and T'Class. Nothing
else is changed.
 
> The type conversions are view conversions, and they never make copies.

View conversions will be kept for tagged types and not introduced for
untagged ones.

> That 
> forces the representation to be compatible. You could change that for 
> by-copy types (although that would have run-time compatibility issues for 
> controlled objects),

Controlled objects are tagged, hence no change here.

> but you can't change that for types that have no copy 
> operation (like tasks and protected objects). So how to do you implement 
> them? Array of task is an untagged type, too, and it certainly should be 
> able to use 'Class.

Sure. T'Class will be a referential object when T is untagged by-reference
type. It will consist of the type tag and a *pointer* to the specific
object (not much different from 4.1.5), and from view conversions ether,
though formally a new object.

When T is by-copy, T'Class is the type tag + a copy of T.

>> I don't ban inheritance of the representation. I want to be able not to do
>> it when I don't need it, e.g. for character and string types.
> 
> But it's not that easy. If you have an array of tasks:
> 
>     type Foo (1 .. 10) of Some_Task with Component_Size => 32;
> 
> and you derive another array of tasks from it:
> 
>    type New_Foo is new Foo with Component_Size => 64;
> 
> This is legal, and you have different representations.

Irrelevant. Ada 83 derivation (cloning) is orthogonal to Ada 95 extension
model. We are talking about the later.

>>> It really kills the entire idea.
>>
>> No, IF String inherited the representation of Wide_Wide_String, THAT would
>> kill the idea.
>>
>> The whole idea is not to inherit irrelevant representations!
> 
> I don't see the problem here; if Root_String is an abstract tagged type,

Java interfaces will not work for characters/strings. No need even to try
it.

>> The bottom line is, I regard Ada 83 construct "type S is new T;" as very
>> useful, and wished it be valid with all specific types without silly
>> exceptions Ada 95 made for tagged types.
> 
> Fair enough. I regard "type S is new T;" as a junk piece of syntax that was 
> inherited from Ada 83, and should never be used. We completely disagree on 
> this one, and there really is nothing worth talking about.
> 
> You previously asked about:
> 
>     type Velocity is new Float;
> 
> That would get you a repremand if you worked for me. You never, ever use the 
> types in Standard (because they're not necessarily portable to other 
> compilers). You derive types based on your actual application requirements:
> 
>    type Velocity is digits 5 range -1.0E+10 .. 1.0E+10;

This is a bad design pattern because it refers to some magic numbers spread
all over the source code, a huge maintenance problem, potentially. The
proper pattern would be:

   type Measurement is digits 5 range -1.0E+10 .. 1.0E+10;
   ...
   type Velocity is new Measurement;
   type Acceleration is new Measurement;
   ...

>>> Because you need operations that work on every object,
>>> copyable or not. Remember, there are no type conversions between types in
>>> different hierarchies.
>>
>> And, this is what different hierarchies are for.
> 
> For what? To make it impossible to pass integers to Text_IO, or to use them 
> to instantiation Text_IO?

It is in the same generic formal class, thus instantiation is possible.

You are confusing generic classes, and classes induced by cloning, and
classes induced by interface inheritance. They are not same.

There is an infinite number of means by which some types could be lumped
into a class. Class is no more than a set of types. E.g. all types which
declarations start at the source code line 123 is a class. That does not
make them possible or not to be used in Text_IO instantiation. That would
be some other class.

>>>> But they are still the same
>>>> hierarchy. You need some fundamental operation which tells that a type
>>>> breaks off the hierarchy.
>>>
>>> Yes, of course all containers ought to be members of the same hierarchy. 
>>> How else would you create generic algorithms?
>>
>> Easily. Cloning borrows all operations. Define algorithm on the original
>> type. Then clone it. Done!
> 
> But you have cloned nothing.

I did types, literals, operations.

> Either you have a conversion to the original 
> type, in which case they belong to the same hierarchy.

This is a possible way to implement cloning. This is not the semantics of.
The semantics is that there is a new set of types, values and operations
with the properties of the original. Nothing more.

> A string class with a mixed & is nonsense. (I think the String & Character 
> in Ada 83 was nonsense, but it's not a problem here.)

It would be interesting to learn how many c.l.a. readers share such an
extreme view.

To me "&" is one of the most important requirements on string class design.
It is also a good test for the language type system maturity.
 
> The only & is String & String = String, and so on for all types.

Totally useless, IMO.

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



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

* Re: Is this expected behavior or not
  2013-04-02  8:44                                                                                                 ` Dmitry A. Kazakov
@ 2013-04-02 21:54                                                                                                   ` Randy Brukardt
  2013-04-03  8:54                                                                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-02 21:54 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:3gv2jwc95otm.pl2aahsh9ox8.dlg@40tude.net...
> On Mon, 1 Apr 2013 19:40:42 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net...
>> ....
>>> The point is that whether you create a totally new string hierarchy or
>>> create one for already existing string types, you will have the issue 
>>> with
>>> "&" (and any other operation with more than one argument/result of 
>>> string
>>> type). That is *independent* on whatever Ada did or not before. It is in
>>> the nature of a multi-method, which "&" is. If you want a hierarchy of
>>> strings you *must* face this problem.
>>
>> No you don't. There are no language-defined multi-methods. String & 
>> String =
>> String is not a multi-method.
>
> Once String becomes member of a class it is. For the operation "&" there
> exist only two possibilities, Either it is a primitive operation of the
> class and so a multi-method, or else it is declared individually on each
> member of the class in separate packages (somewhere after the freezing
> point). The later variant is so silly that I don't even consider it.

I agree that latter variant is silly, but the notion that somehow "&" 
becomes a multi-method simply because it exists makes no sense. "=" is not a 
multi-method in Ada today for tagged types; "&" would work the same way - it 
does not take items of different types unless you explicitly convert them. 
Maybe you have a different idea of a multimethod than I do??

>> You, the user, can define such operations, of
>> course, but then you have the deal with the consequences. Generally, it's
>> best if you don't do that.
>
> What is the use of a string type without operations?

Huh? There are predefined single-type operations. If you want mixed type 
operations, you have to define them, but it's usually a bad idea to do so. 
You're almost always better off with 'Class operands if you need type 
mixing -- for type resolution reasons (not even mentioning runtime issues).

...
> You said that it would not fit into Ada 83 derived types model. I answered
> that it never considered within that model. The model to augment is Ada 95
> tagged types.

Tagged types need no augmentation -- they only work because they are 
by-reference types. They can't work without that, and you (rightly) want to 
get rid of that.

>> You have to be able to inherit
>> implementation of operations, for all types.
>
> It is already not so. See Ada 95 abstract primitive operations and
> operations dispatching in the result. They are NOT inherited. The
> programmer is asked to override them, because the compiler has no idea how
> to implement them.

Abstract operations have no implementation to override. Constructor 
functions are a special case where you would never want to share the 
implementation anyway. The fact that other functions aren't extended is a 
mistake in Ada, it makes it impractical to have those in your interfaces.

The Claw Builder has types with a lot of functions and abstract routines, 
and the net effect is that it takes a week or more to create a single 
extension of the type - just to type in all of the bodies required. And the 
result of that is that extensions simply don't get built because the burden 
is too high.

>> And there exist plenty of Ada
>> types for which copying is not allowed.
>
> No problem. See above. All primitive operation will be inherited abstract
> if the representation is not inherited and no [user-defined] conversion
> defined (e.g. for a by-reference type).

That was a bad idea for Ada 95 (there are pretty severe visibility issues 
associated with it), and I don't think it can be extended. In any case, that 
extends the problem of creating extensions -- it would be so diifficult and 
time-consuming that it almost never would be done. (Imagine extending 
Ada.Containers.Vectors if every routine became abstract. You'd never bother, 
because the effort to even write something to compiler would be so extreme. 
It's the exact opposite of agile programming [the only sane way to program, 
IMHO].

>> The only way to implement those is
>> via some sort of dispatching, and the need poisons the possibility of
>> omitting tags, even for "specific" operations.
>
> I don't understand where you get this. The model is exactly the model of
> tagged types, but without specific objects required to keep the tag. The
> only thing it influences is view conversions between T and T'Class. 
> Nothing
> else is changed.

When you dispatch to an inherited routine, you directly call that routine 
with the operands view converted (which cannot make copies in the general 
case). The only way for this to work is for the low-level operations of the 
type to be implemented with dispatching calls -- this is exactly how generic 
units work in Janus/Ada. This requires a descriptor of some sort with every 
object and has the effect of re-dispatching.

You are suggesting making such operations illegal (no inheritance), which 
does eliminate that problem but would make the resulting language 
unusable -- certainly in an agile sense. (The average private type having 
more than 100 operations once inherited and low-level ones that you want to 
break out are included.)

>> The type conversions are view conversions, and they never make copies.
>
> View conversions will be kept for tagged types and not introduced for
> untagged ones.

Untagged types already have view conversions (it's what you pass to "in out" 
parameters in calls). You're 20 years too late with that idea.

>> That
>> forces the representation to be compatible. You could change that for
>> by-copy types (although that would have run-time compatibility issues for
>> controlled objects),
>
> Controlled objects are tagged, hence no change here.

A component is an object; I'm talking about untagged objects with controlled 
components here.

>> but you can't change that for types that have no copy
>> operation (like tasks and protected objects). So how to do you implement
>> them? Array of task is an untagged type, too, and it certainly should be
>> able to use 'Class.
>
> Sure. T'Class will be a referential object when T is untagged by-reference
> type. It will consist of the type tag and a *pointer* to the specific
> object (not much different from 4.1.5), and from view conversions ether,
> though formally a new object.
>
> When T is by-copy, T'Class is the type tag + a copy of T.

Wow! And this is supposed to be a *simplification*??? :-)

>>> I don't ban inheritance of the representation. I want to be able not to 
>>> do
>>> it when I don't need it, e.g. for character and string types.
>>
>> But it's not that easy. If you have an array of tasks:
>>
>>     type Foo (1 .. 10) of Some_Task with Component_Size => 32;
>>
>> and you derive another array of tasks from it:
>>
>>    type New_Foo is new Foo with Component_Size => 64;
>>
>> This is legal, and you have different representations.
>
> Irrelevant. Ada 83 derivation (cloning) is orthogonal to Ada 95 extension
> model. We are talking about the later.

Actually, there is only one model of inheritance in Ada. We're not making 
another one! There are slight differences in how the inheritance happens, 
but it's minor. In any case, there is no reason to separate derived from 
anything else: "type cloning" and "extension without new components" are the 
same thing -- you get a new type that's related to the current one only via 
explicit conversion and class-wide operations.

>>>> It really kills the entire idea.
>>>
>>> No, IF String inherited the representation of Wide_Wide_String, THAT 
>>> would
>>> kill the idea.
>>>
>>> The whole idea is not to inherit irrelevant representations!
>>
>> I don't see the problem here; if Root_String is an abstract tagged type,
>
> Java interfaces will not work for characters/strings. No need even to try
> it.

Java interfaces will not work for anything. No need to even try. :-) And 
who's talking about Java, anyway?

I'm interested in what we can do with tagged types. Forget the silly 
interfaces, or call it an interface if that makes people feel better (that's 
what we did with iterators, but it doesn't actually buy you anything). It's 
an Ada 95 abstract type.

...
>> That would get you a repremand if you worked for me. You never, ever use 
>> the
>> types in Standard (because they're not necessarily portable to other
>> compilers). You derive types based on your actual application 
>> requirements:
>>
>>    type Velocity is digits 5 range -1.0E+10 .. 1.0E+10;
>
> This is a bad design pattern because it refers to some magic numbers 
> spread
> all over the source code, a huge maintenance problem, potentially.

People how spread "magic numbers" all over the source code are idiots. In a 
real program, these would be constants declared in an appropriate package. 
That's Ada 101. I'm not putting that sort of organization in little 
examples, I would hope that is a given around here.

> The proper pattern would be:
>
>   type Measurement is digits 5 range -1.0E+10 .. 1.0E+10;
>   ...
>   type Velocity is new Measurement;
>   type Acceleration is new Measurement;
>   ...

This is a terrible design pattern because it puts unrelated types together 
(and, allows them to be converted to a common ancestor, which almost always 
is a bug - especially if we had Measurement'Class). If I find that in our 
code somewhere, I'm going to remove it and try to find the offending 
programmer for an educational moment. :-)

>>>> Because you need operations that work on every object,
>>>> copyable or not. Remember, there are no type conversions between types 
>>>> in
>>>> different hierarchies.
>>>
>>> And, this is what different hierarchies are for.
>>
>> For what? To make it impossible to pass integers to Text_IO, or to use 
>> them
>> to instantiation Text_IO?
>
> It is in the same generic formal class, thus instantiation is possible.

The "generic formal class" = hierarchy in Ada; if you split the hierarchy, 
then it's no longer in the same formal class. (That's the *meaning* of 
"class" in Ada; if you wanted truly unrelated things to work, it would have 
to be a "category" instead -- but there are no shared operations for 
categories as that does not make sense. And "categories" are never 
inherited.)

> You are confusing generic classes, and classes induced by cloning, and
> classes induced by interface inheritance. They are not same.

I'm not confusing anything -- they *are* the same thing in Ada. I suppose 
you could introduce a whole new boatload of complexity to the language 
definition to make them different, but how you can call that a 
simplification is beyond me.

> There is an infinite number of means by which some types could be lumped
> into a class. Class is no more than a set of types. E.g. all types which
> declarations start at the source code line 123 is a class. That does not
> make them possible or not to be used in Text_IO instantiation. That would
> be some other class.

No, that's a "category" (in Ada terminology). Limited types are a 
"category", because that's not an inherited property. "Class" is always 
inherited: all members of a hierarchy rooted at a class have the same 
properties.

>>>>> But they are still the same
>>>>> hierarchy. You need some fundamental operation which tells that a type
>>>>> breaks off the hierarchy.
>>>>
>>>> Yes, of course all containers ought to be members of the same 
>>>> hierarchy.
>>>> How else would you create generic algorithms?
>>>
>>> Easily. Cloning borrows all operations. Define algorithm on the original
>>> type. Then clone it. Done!
>>
>> But you have cloned nothing.
>
> I did types, literals, operations.
>
>> Either you have a conversion to the original
>> type, in which case they belong to the same hierarchy.
>
> This is a possible way to implement cloning. This is not the semantics of.
> The semantics is that there is a new set of types, values and operations
> with the properties of the original. Nothing more.

If they allow conversion (including implicitly to the class-wide root of the 
class) and instantiation, they're members of the same hierarchy. So it's the 
same as any other kind of extension inheritance (essentially a null 
extension). If it *doesn't* allow conversion and instantiation, then it's 
pretty useless (and it's not the same as Ada is today, which you claim you 
want to support).

You do know that there are special rules for null extension so that you 
don't have to override any functions returning the type? Unlike normal 
extension, you only have to override abstract operations (which there should 
be none). So there would be no semantic difference between writing (if you 
could):
    type T is new W;
and (which you can write):
    type T is new W with null record;

I'm not actually sure why the former is disallowed, I think it's an intent 
to highlight the difference between tagged and untagged types. (And I don't 
know why we would want to highlight that!)

>> A string class with a mixed & is nonsense. (I think the String & 
>> Character
>> in Ada 83 was nonsense, but it's not a problem here.)
>
> It would be interesting to learn how many c.l.a. readers share such an
> extreme view.
>
> To me "&" is one of the most important requirements on string class 
> design.
> It is also a good test for the language type system maturity.
>
>> The only & is String & String = String, and so on for all types.
>
> Totally useless, IMO.

Fair enough, we can agree to disagree on all of this. That's how Ada works 
today, and I've hardly ever heard anyone claim that Ada array types are 
"totally useless".

                                    Randy.





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

* Re: Is this expected behavior or not
  2013-04-02 21:54                                                                                                   ` Randy Brukardt
@ 2013-04-03  8:54                                                                                                     ` Dmitry A. Kazakov
  2013-04-04  0:04                                                                                                       ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-03  8:54 UTC (permalink / raw)


On Tue, 2 Apr 2013 16:54:01 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:3gv2jwc95otm.pl2aahsh9ox8.dlg@40tude.net...
>> On Mon, 1 Apr 2013 19:40:42 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net...
>>> ....
>>>> The point is that whether you create a totally new string hierarchy or
>>>> create one for already existing string types, you will have the issue with
>>>> "&" (and any other operation with more than one argument/result of string
>>>> type). That is *independent* on whatever Ada did or not before. It is in
>>>> the nature of a multi-method, which "&" is. If you want a hierarchy of
>>>> strings you *must* face this problem.
>>>
>>> No you don't. There are no language-defined multi-methods. String & 
>>> String = String is not a multi-method.
>>
>> Once String becomes member of a class it is. For the operation "&" there
>> exist only two possibilities, Either it is a primitive operation of the
>> class and so a multi-method, or else it is declared individually on each
>> member of the class in separate packages (somewhere after the freezing
>> point). The later variant is so silly that I don't even consider it.
> 
> I agree that latter variant is silly, but the notion that somehow "&" 
> becomes a multi-method simply because it exists makes no sense. "=" is not a 
> multi-method in Ada today for tagged types;

Assignment should certainly be a multi-method, because in some cases you
want to be able to assign one type of the hierarchy to another. Assignment
is a bit special case because the target's tag cannot be changed anyway.
That reduces the number of use-cases for mixed types. Others could be
further reduced using constrained subtypes, but they still exist.

As a multi-method use case consider a tagged class with the operations "="
and "<" defined. These must support mixed types almost always.

> "&" would work the same way - it 
> does not take items of different types unless you explicitly convert them. 
> Maybe you have a different idea of a multimethod than I do??

If you have more than one controlled argument/result of the same type, that
makes it a multi-method. The natural consequence of this is that all
possible combinations of types from the hierarchy are specific bodies to
inherit/override. In Ada 95 only the bodies when all types are same can be
overridden. Statically the compiler prevents calls to mixed types bodies,
but they nevertheless exist and can be reached through dispatch. In that
case it works as if the body were "rase Constraint_Error." This hack won't
work for &, =, <, <= etc. Those require almost all combinations to work.

>>> You, the user, can define such operations, of
>>> course, but then you have the deal with the consequences. Generally, it's
>>> best if you don't do that.
>>
>> What is the use of a string type without operations?
> 
> Huh? There are predefined single-type operations. If you want mixed type 
> operations, you have to define them,

It would be a combinatorial explosion of variants and a huge issue with
visibility. The language should support this use case, because it is a
pattern for all dyadic operations, assignment, comparisons.

> but it's usually a bad idea to do so. 
> You're almost always better off with 'Class operands if you need type 
> mixing -- for type resolution reasons (not even mentioning runtime issues).

That does not solve the problem, you will get Constraint_Error.

The only pattern that sometimes works is recursive cascaded dispatch. That
is when you make one argument controlled and another class-wide. I used it
for "=" and "<" multi-method operations of the target type hierarchy of
smart pointers. I needed this to be able to have ordered collections of
smart pointers to such objects when pointers are ordered by the objects
they point to. It is extremely tedious, involves recursive calls and
explicit tag comparisons for ancestry. It won't work with for operations
like &, which has two arguments and the result.

>>> And there exist plenty of Ada
>>> types for which copying is not allowed.
>>
>> No problem. See above. All primitive operation will be inherited abstract
>> if the representation is not inherited and no [user-defined] conversion
>> defined (e.g. for a by-reference type).
> 
> That was a bad idea for Ada 95 (there are pretty severe visibility issues 
> associated with it), and I don't think it can be extended.

It was a great Ada 95 idea, because covariant out-operations are unsafe to
inherit under type extension.

*The compiler shall not make any assumptions*

> In any case, that 
> extends the problem of creating extensions -- it would be so diifficult and 
> time-consuming that it almost never would be done.

It is not an extension, it meant to be the same interface and a completely
different representation. Extension is the same interface and extended
representation.

Anyway, the point is, that the compiler shall inherit a body IF AND ONLY IF
it knows that this would be safe to do. That is the following cases:

1. Any operation when the representation is same

2. In-operation when the representation is extension or constraint

3. Out-operation when the representation is generalization (lifted
constraint) [Ada does not have this, as an example consider extension of an
enumeration type]

4. User-defined conversion defined, programmer's responsibility [Ada does
not have this]

On top of that come pre- and post-conditions which may in their turn
disallow inheritance of the body.

>>> The only way to implement those is
>>> via some sort of dispatching, and the need poisons the possibility of
>>> omitting tags, even for "specific" operations.
>>
>> I don't understand where you get this. The model is exactly the model of
>> tagged types, but without specific objects required to keep the tag. The
>> only thing it influences is view conversions between T and T'Class. 
>> Nothing else is changed.
> 
> When you dispatch to an inherited routine, you directly call that routine 
> with the operands view converted (which cannot make copies in the general 
> case).

For by-copy types dispatching call will be copy-in / copy-out. The
representation of T'Class is tag + value. Tag is stripped, value passed
through.

For by-reference untagged types dispatching call will pass the reference.
The representation of T'Class is tag + pointer. Tag is stripped, reference
passed through.

>>> That
>>> forces the representation to be compatible. You could change that for
>>> by-copy types (although that would have run-time compatibility issues for
>>> controlled objects),
>>
>> Controlled objects are tagged, hence no change here.
> 
> A component is an object; I'm talking about untagged objects with controlled 
> components here.

No change either. If a by-copy object passed by value has a controlled
component that component is copied-in and out using Adjust and
Finalization.
 
>>> but you can't change that for types that have no copy
>>> operation (like tasks and protected objects). So how to do you implement
>>> them? Array of task is an untagged type, too, and it certainly should be
>>> able to use 'Class.
>>
>> Sure. T'Class will be a referential object when T is untagged by-reference
>> type. It will consist of the type tag and a *pointer* to the specific
>> object (not much different from 4.1.5), and from view conversions ether,
>> though formally a new object.
>>
>> When T is by-copy, T'Class is the type tag + a copy of T.
> 
> Wow! And this is supposed to be a *simplification*??? :-)

Yes. It is much simpler to view tagged types as a special case [definite
representation constraint] of a more general model that encompasses all
types.

>>>>> It really kills the entire idea.
>>>>
>>>> No, IF String inherited the representation of Wide_Wide_String, THAT 
>>>> would kill the idea.
>>>>
>>>> The whole idea is not to inherit irrelevant representations!
>>>
>>> I don't see the problem here; if Root_String is an abstract tagged type,
>>
>> Java interfaces will not work for characters/strings. No need even to try it.
> 
> Java interfaces will not work for anything. No need to even try. :-) And 
> who's talking about Java, anyway?

You want strings hierarchy of one level depth. That won't work.

> I'm interested in what we can do with tagged types. Forget the silly 
> interfaces, or call it an interface if that makes people feel better (that's 
> what we did with iterators, but it doesn't actually buy you anything). It's 
> an Ada 95 abstract type.

If so, allow to inherit from more than one. Allow to inherit only interface
from such a type. You have the problem of "&" at hand. It cannot be solved
without the above mechanisms. And multi-method and MI is only a start. The
real problem is *full* MD as "&" is defined on String and Character.

>> The proper pattern would be:
>>
>>   type Measurement is digits 5 range -1.0E+10 .. 1.0E+10;
>>   ...
>>   type Velocity is new Measurement;
>>   type Acceleration is new Measurement;
>>   ...
> 
> This is a terrible design pattern because it puts unrelated types together 
> (and, allows them to be converted to a common ancestor, which almost always 
> is a bug - especially if we had Measurement'Class).

They are related, Acceleration is computed from Velocity and Duration. On
top of that come a huge pile of generics (can't rid of them) instantiated
with Measurement, e.g. I/O, GUI stuff. In real-life case you can't do that
with individual types. You need a class and this is what Measurement is
for.

>>> Either you have a conversion to the original
>>> type, in which case they belong to the same hierarchy.
>>
>> This is a possible way to implement cloning. This is not the semantics of.
>> The semantics is that there is a new set of types, values and operations
>> with the properties of the original. Nothing more.
> 
> If they allow conversion (including implicitly to the class-wide root of the 
> class) and instantiation, they're members of the same hierarchy.

The semantics for tagged types (if they were supported) should be creating
a new type for each parent type.

   type T is new Ada,Finalization.Controlled with ...;
   type Q is new T;

   X : Q;
   Y : Ada.Finalization.Controlled'Class := X; -- Type error
   Z : Ada.Finalization.Controlled'Class := T (X); -- OK

Q is not an extension of Ada,Finalization.Controlled. It is of some
anonymous type cloned from Ada,Finalization.Controlled:

   type <anonymous> is new Ada,Finalization.Controlled;

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



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

* Re: Is this expected behavior or not
  2013-04-03  8:54                                                                                                     ` Dmitry A. Kazakov
@ 2013-04-04  0:04                                                                                                       ` Randy Brukardt
  2013-04-04  8:26                                                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-04  0:04 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1gkxiwepaxvtt$.u3ly33rbwthf.dlg@40tude.net...
> On Tue, 2 Apr 2013 16:54:01 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:3gv2jwc95otm.pl2aahsh9ox8.dlg@40tude.net...
>>> On Mon, 1 Apr 2013 19:40:42 -0500, Randy Brukardt wrote:
>>>
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>>> news:1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net...
>>>> ....
>>>>> The point is that whether you create a totally new string hierarchy or
>>>>> create one for already existing string types, you will have the issue 
>>>>> with
>>>>> "&" (and any other operation with more than one argument/result of 
>>>>> string
>>>>> type). That is *independent* on whatever Ada did or not before. It is 
>>>>> in
>>>>> the nature of a multi-method, which "&" is. If you want a hierarchy of
>>>>> strings you *must* face this problem.
>>>>
>>>> No you don't. There are no language-defined multi-methods. String &
>>>> String = String is not a multi-method.
>>>
>>> Once String becomes member of a class it is. For the operation "&" there
>>> exist only two possibilities, Either it is a primitive operation of the
>>> class and so a multi-method, or else it is declared individually on each
>>> member of the class in separate packages (somewhere after the freezing
>>> point). The later variant is so silly that I don't even consider it.
>>
>> I agree that latter variant is silly, but the notion that somehow "&"
>> becomes a multi-method simply because it exists makes no sense. "=" is 
>> not a
>> multi-method in Ada today for tagged types;
>
> Assignment should certainly be a multi-method, because in some cases you
> want to be able to assign one type of the hierarchy to another. Assignment
> is a bit special case because the target's tag cannot be changed anyway.
> That reduces the number of use-cases for mixed types. Others could be
> further reduced using constrained subtypes, but they still exist.
>
> As a multi-method use case consider a tagged class with the operations "="
> and "<" defined. These must support mixed types almost always.
>
>> "&" would work the same way - it
>> does not take items of different types unless you explicitly convert 
>> them.
>> Maybe you have a different idea of a multimethod than I do??
>
> If you have more than one controlled argument/result of the same type, 
> that
> makes it a multi-method. The natural consequence of this is that all
> possible combinations of types from the hierarchy are specific bodies to
> inherit/override. In Ada 95 only the bodies when all types are same can be
> overridden. Statically the compiler prevents calls to mixed types bodies,
> but they nevertheless exist and can be reached through dispatch. In that
> case it works as if the body were "rase Constraint_Error." This hack won't
> work for &, =, <, <= etc. Those require almost all combinations to work.

I see where you are coming from, but I don't agree with any of it on a 
fundamental level: mixing types in operations is virtually always an error 
(either a real mistake or a design error). So here again we must agree to 
disagree.

>>>> You, the user, can define such operations, of
>>>> course, but then you have the deal with the consequences. Generally, 
>>>> it's
>>>> best if you don't do that.
>>>
>>> What is the use of a string type without operations?
>>
>> Huh? There are predefined single-type operations. If you want mixed type
>> operations, you have to define them,
>
> It would be a combinatorial explosion of variants and a huge issue with
> visibility. The language should support this use case, because it is a
> pattern for all dyadic operations, assignment, comparisons.

I don't believe that these use cases are at all common. I don't recall any 
such cases in Claw, for example, which uses Ada 95 inheritance extensively.

>> but it's usually a bad idea to do so.
>> You're almost always better off with 'Class operands if you need type
>> mixing -- for type resolution reasons (not even mentioning runtime 
>> issues).
>
> That does not solve the problem, you will get Constraint_Error.

You don't get Constraint_Error when one of the arguments is class-wide:

     function Is_Same (Left : A_Type; Right : Root_Type'Class) return 
Boolean;

There is no automatic reason for this to raise Constraint_Error. You do have 
to implement this, of course, and whether that can easily be done depends on 
the operations of your class-wide type -- but that's all under the control 
of the programmer.

> The only pattern that sometimes works is recursive cascaded dispatch. That
> is when you make one argument controlled and another class-wide.

Gosh, that's what I was talking from the beginning.

> I used it for "=" and "<" multi-method operations of the target type 
> hierarchy of
> smart pointers. I needed this to be able to have ordered collections of
> smart pointers to such objects when pointers are ordered by the objects
> they point to. It is extremely tedious, involves recursive calls and
> explicit tag comparisons for ancestry. It won't work with for operations
> like &, which has two arguments and the result.

You don't want mixed operations in cases like "&", ever. It simply doesn't 
make any sense from a resolution prespective. You want to fix resolution by 
introducing a set of very complex preference rules. Based on our experience 
with much easier changes (like resolving routines inherited from 
interfaces), the likelihood of getting that right is about 0% - it would 
take years of detailed work to create a model that both worked and did not 
introduce incompatibilities. It would require there to be critical bugs in 
Ada (or critical needs) for the (current) ARG to take on such changes. You 
aren't even willing to write up real use-cases where the existing language 
has problems (because I've asked that you do that in the past) -- without 
those there is no chance that any significant changes will be entertained 
here.

...
>> In any case, that
>> extends the problem of creating extensions -- it would be so diifficult 
>> and
>> time-consuming that it almost never would be done.
>
> It is not an extension, it meant to be the same interface and a completely
> different representation. Extension is the same interface and extended
> representation.

Interfaces alone are worthless. The only thing that makes inheritance worth 
the effort is the ability to share implementations.

> Anyway, the point is, that the compiler shall inherit a body IF AND ONLY 
> IF
> it knows that this would be safe to do. That is the following cases:
>
> 1. Any operation when the representation is same
>
> 2. In-operation when the representation is extension or constraint
>
> 3. Out-operation when the representation is generalization (lifted
> constraint) [Ada does not have this, as an example consider extension of 
> an
> enumeration type]
>
> 4. User-defined conversion defined, programmer's responsibility [Ada does
> not have this]
>
> On top of that come pre- and post-conditions which may in their turn
> disallow inheritance of the body.

Besides being incompatible, I suspect that this would just be too complex 
for the average Ada user to understand. It took me a long time to understand 
inheritance at all -- I never did understand it in Ada 83 and it took a huge 
amount of effort (and creating several large libraries using it) before I 
got any feeling for it at all.

>>>> The only way to implement those is
>>>> via some sort of dispatching, and the need poisons the possibility of
>>>> omitting tags, even for "specific" operations.
>>>
>>> I don't understand where you get this. The model is exactly the model of
>>> tagged types, but without specific objects required to keep the tag. The
>>> only thing it influences is view conversions between T and T'Class.
>>> Nothing else is changed.
>>
>> When you dispatch to an inherited routine, you directly call that routine
>> with the operands view converted (which cannot make copies in the general
>> case).
>
> For by-copy types dispatching call will be copy-in / copy-out. The
> representation of T'Class is tag + value. Tag is stripped, value passed
> through.
>
> For by-reference untagged types dispatching call will pass the reference.
> The representation of T'Class is tag + pointer. Tag is stripped, reference
> passed through.

What about the majority of types which are neither By-Copy nor By-Reference? 
Such types allow the compiler to chose how they're passed, and that would 
seem to be a huge problem for this model. You'd have to forcibly specify one 
or the other for all types, which is certain to be incompatible with 
existing implementations.

It strikes me that the model of stripping tags means that type conversion of 
an object to a class-wide type would effectively change the tag (if the 
routine was inherited or called by a conversion of an operand). That would 
mean that the behavior of such a conversion would be very different for an 
untagged type and for a tagged type. Not sure if that is a real problem, but 
it certainly would be the sort of thing we would not want to be true. 
(Essentially this would mean that re-dispatching is not possible for 
untagged objects. I agree that re-dispatching is usually a mistake, but 
sometimes you need it -- we did use it in Claw in a few instances for 
message delivery, for example.)

>>>> That
>>>> forces the representation to be compatible. You could change that for
>>>> by-copy types (although that would have run-time compatibility issues 
>>>> for
>>>> controlled objects),
>>>
>>> Controlled objects are tagged, hence no change here.
>>
>> A component is an object; I'm talking about untagged objects with 
>> controlled
>> components here.
>
> No change either. If a by-copy object passed by value has a controlled
> component that component is copied-in and out using Adjust and
> Finalization.

That's the problem. If that is done in existing code, you have an 
incompatibility (because the same code does something different now). It 
also could cause problems if such a call occurred inside of an Adjust or 
Finalize, you could unintentionally cause an infinite regress.

>>>> but you can't change that for types that have no copy
>>>> operation (like tasks and protected objects). So how to do you 
>>>> implement
>>>> them? Array of task is an untagged type, too, and it certainly should 
>>>> be
>>>> able to use 'Class.
>>>
>>> Sure. T'Class will be a referential object when T is untagged 
>>> by-reference
>>> type. It will consist of the type tag and a *pointer* to the specific
>>> object (not much different from 4.1.5), and from view conversions ether,
>>> though formally a new object.
>>>
>>> When T is by-copy, T'Class is the type tag + a copy of T.
>>
>> Wow! And this is supposed to be a *simplification*??? :-)
>
> Yes. It is much simpler to view tagged types as a special case [definite
> representation constraint] of a more general model that encompasses all
> types.

A more general model that is many times more complex than the existing 
model. What exactly is being simplified? It's like the 1986 tax 
simplification in the US; they eventually renamed it to "tax reform" because 
in the end nothing was simplified.

>>>>>> It really kills the entire idea.
>>>>>
>>>>> No, IF String inherited the representation of Wide_Wide_String, THAT
>>>>> would kill the idea.
>>>>>
>>>>> The whole idea is not to inherit irrelevant representations!
>>>>
>>>> I don't see the problem here; if Root_String is an abstract tagged 
>>>> type,
>>>
>>> Java interfaces will not work for characters/strings. No need even to 
>>> try it.
>>
>> Java interfaces will not work for anything. No need to even try. :-) And
>> who's talking about Java, anyway?
>
> You want strings hierarchy of one level depth. That won't work.

I don't even know what you mean by "one level depth", but I've already 
prototyped such a string type and it works fine -- better than the existing 
types.

>> I'm interested in what we can do with tagged types. Forget the silly
>> interfaces, or call it an interface if that makes people feel better 
>> (that's
>> what we did with iterators, but it doesn't actually buy you anything). 
>> It's
>> an Ada 95 abstract type.
>
> If so, allow to inherit from more than one.  Allow to inherit only 
> interface
> from such a type.

That's why we'd probably define it as an interface, so that misguided people 
like you will feel better. :-) I find no value whatsoever to interfaces 
without a skelton shared implementation, so I want components and concrete 
operations in any type. And implementing full MI is prohibitively expensive, 
on top of which it's usually not the best solution anyway.

> You have the problem of "&" at hand. It cannot be solved
> without the above mechanisms. And multi-method and MI is only a start. The
> real problem is *full* MD as "&" is defined on String and Character.

We can agree to disagree on the above. You are just babbling in my view -- I 
see no problem at all with "&". Combining different types in an ad-hoc way 
is the same as not having typing at all in terms of error detection. You 
need more than just a definition of what happens when type A is converted to 
type B, you also have to require almost all conversions to be explicit. And 
once you do that, multi-methods are virtually never needed.

...
>>> The proper pattern would be:
>>>
>>>   type Measurement is digits 5 range -1.0E+10 .. 1.0E+10;
>>>   ...
>>>   type Velocity is new Measurement;
>>>   type Acceleration is new Measurement;
>>>   ...
>>
>> This is a terrible design pattern because it puts unrelated types 
>> together
>> (and, allows them to be converted to a common ancestor, which almost 
>> always
>> is a bug - especially if we had Measurement'Class).
>
> They are related, Acceleration is computed from Velocity and Duration. On
> top of that come a huge pile of generics (can't rid of them) instantiated
> with Measurement, e.g. I/O, GUI stuff. In real-life case you can't do that
> with individual types. You need a class and this is what Measurement is
> for.

Your real-life is obviously completely different than mine. There are almost 
no generics in any of our code (especially in the compiler). And even if 
there were, I'd be happy to have as many instantiations as needed -- code 
shared generic instances are pretty cheap to create.

...
>>>> Either you have a conversion to the original
>>>> type, in which case they belong to the same hierarchy.
>>>
>>> This is a possible way to implement cloning. This is not the semantics 
>>> of.
>>> The semantics is that there is a new set of types, values and operations
>>> with the properties of the original. Nothing more.
>>
>> If they allow conversion (including implicitly to the class-wide root of 
>> the
>> class) and instantiation, they're members of the same hierarchy.
>
> The semantics for tagged types (if they were supported) should be creating
> a new type for each parent type.
>
>   type T is new Ada,Finalization.Controlled with ...;
>   type Q is new T;
>
>   X : Q;
>   Y : Ada.Finalization.Controlled'Class := X; -- Type error
>   Z : Ada.Finalization.Controlled'Class := T (X); -- OK
>
> Q is not an extension of Ada,Finalization.Controlled. It is of some
> anonymous type cloned from Ada,Finalization.Controlled:
>
>   type <anonymous> is new Ada,Finalization.Controlled;

Sure, but what does this mean? If there is no conversion or instantiation 
associated with this new type, it's useless. (You'd need to duplicate all of 
the code associated with it.) And if there is, it's not a separate 
hierarchy.

Anyway, this is getting pointless (especially this last part). I think this 
discussion is pretty much done, so I'm going to try to refrain from 
answering any more on this.

                              Randy.





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

* Re: Is this expected behavior or not
  2013-04-04  0:04                                                                                                       ` Randy Brukardt
@ 2013-04-04  8:26                                                                                                         ` Dmitry A. Kazakov
  2013-04-04 20:31                                                                                                           ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-04  8:26 UTC (permalink / raw)


On Wed, 3 Apr 2013 19:04:24 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1gkxiwepaxvtt$.u3ly33rbwthf.dlg@40tude.net...

>> If you have more than one controlled argument/result of the same type, 
>> that makes it a multi-method. The natural consequence of this is that all
>> possible combinations of types from the hierarchy are specific bodies to
>> inherit/override. In Ada 95 only the bodies when all types are same can be
>> overridden. Statically the compiler prevents calls to mixed types bodies,
>> but they nevertheless exist and can be reached through dispatch. In that
>> case it works as if the body were "rase Constraint_Error." This hack won't
>> work for &, =, <, <= etc. Those require almost all combinations to work.
> 
> I see where you are coming from, but I don't agree with any of it on a 
> fundamental level: mixing types in operations is virtually always an error 
> (either a real mistake or a design error).

How is it an error to compare String and Wide_String?

> I don't believe that these use cases are at all common. I don't recall any 
> such cases in Claw, for example, which uses Ada 95 inheritance extensively.

That is because GUI does not require dyadic operations at all. There are
few cases for MD though. E.g.

   procedure Render (Surface : in out Device_Type; Shape : Geometric_Type);

And of course:

   procedure Set_Text (Control : Edit_Box; Text : Root_String_Type);

>> The only pattern that sometimes works is recursive cascaded dispatch. That
>> is when you make one argument controlled and another class-wide.
> 
> Gosh, that's what I was talking from the beginning.

It works only with dyadic operations, procedures or else functions
returning an alien type.

>> I used it for "=" and "<" multi-method operations of the target type 
>> hierarchy of
>> smart pointers. I needed this to be able to have ordered collections of
>> smart pointers to such objects when pointers are ordered by the objects
>> they point to. It is extremely tedious, involves recursive calls and
>> explicit tag comparisons for ancestry. It won't work with for operations
>> like &, which has two arguments and the result.
> 
> You don't want mixed operations in cases like "&", ever.

Non-starter for strings.

> It simply doesn't 
> make any sense from a resolution prespective. You want to fix resolution by 
> introducing a set of very complex preference rules.

Actually I want these rules defined by the programmer. And resolution is
only the issue with the operations returning the type, e.g. literals. One
cannot have both covariant result factories and multi-method operations. If
I ran the circus I would try to define rules that would prohibit
declaration of potentially conflicting operations, like:

   type T is ...; -- Untagged class

   function Generator return T;
   function "=" (L, R  : T) return Boolean;

This should be an error unless preference rules defined by the programmer
for T.

> Based on our experience 
> with much easier changes (like resolving routines inherited from 
> interfaces), the likelihood of getting that right is about 0% - it would 
> take years of detailed work to create a model that both worked and did not 
> introduce incompatibilities.

Yes, it is a serious work - a type system overhaul. You cannot fix it
without careful design.

>>> In any case, that
>>> extends the problem of creating extensions -- it would be so diifficult 
>>> and time-consuming that it almost never would be done.
>>
>> It is not an extension, it meant to be the same interface and a completely
>> different representation. Extension is the same interface and extended
>> representation.
> 
> Interfaces alone are worthless. The only thing that makes inheritance worth 
> the effort is the ability to share implementations.

Implementation /= representations. You can share class-wide operations and
inherit primitive operations without sharing the representation.

>> Anyway, the point is, that the compiler shall inherit a body IF AND ONLY IF
>> it knows that this would be safe to do. That is the following cases:
>>
>> 1. Any operation when the representation is same
>>
>> 2. In-operation when the representation is extension or constraint
>>
>> 3. Out-operation when the representation is generalization (lifted
>> constraint) [Ada does not have this, as an example consider extension of 
>> an enumeration type]
>>
>> 4. User-defined conversion defined, programmer's responsibility [Ada does
>> not have this]
>>
>> On top of that come pre- and post-conditions which may in their turn
>> disallow inheritance of the body.
> 
> Besides being incompatible,

? I merely explained why Ada 95 design choice was right [#2].

> I suspect that this would just be too complex 
> for the average Ada user to understand.

It need not to be understood. The programmer will be asked to override
operation or else to make type abstract, just as Ada 95 did.

>>>>> The only way to implement those is
>>>>> via some sort of dispatching, and the need poisons the possibility of
>>>>> omitting tags, even for "specific" operations.
>>>>
>>>> I don't understand where you get this. The model is exactly the model of
>>>> tagged types, but without specific objects required to keep the tag. The
>>>> only thing it influences is view conversions between T and T'Class.
>>>> Nothing else is changed.
>>>
>>> When you dispatch to an inherited routine, you directly call that routine
>>> with the operands view converted (which cannot make copies in the general
>>> case).
>>
>> For by-copy types dispatching call will be copy-in / copy-out. The
>> representation of T'Class is tag + value. Tag is stripped, value passed
>> through.
>>
>> For by-reference untagged types dispatching call will pass the reference.
>> The representation of T'Class is tag + pointer. Tag is stripped, reference
>> passed through.
> 
> What about the majority of types which are neither By-Copy nor By-Reference? 
> Such types allow the compiler to chose how they're passed, and that would 
> seem to be a huge problem for this model.

Not at all, the compiler is free to choose, so it must. [I don't consider
schizophrenic compilers choosing one way and doing in another. That does
not work with any model.]

> You'd have to forcibly specify one 
> or the other for all types, which is certain to be incompatible with 
> existing implementations.

The compiler vendor simply follows the choice he made before.
 
> It strikes me that the model of stripping tags means that type conversion of 
> an object to a class-wide type would effectively change the tag (if the 
> routine was inherited or called by a conversion of an operand).

Yes, re-dispatch is a broken thing. Don't do it, because it is ambiguous in
general case when objects do not have an identity. By-copy scalar types are
such things. There is nothing which could distinguish Integer 13 from
Long_Integer 13 except the context. Once you dispatched that information is
lost. There is no way back.

> That would 
> mean that the behavior of such a conversion would be very different for an 
> untagged type and for a tagged type.

Not different. It is just so that tagged types per design have type
identity. Other types simply don't have it.

For an untagged by-reference type an identity still could be added through
the Rosen's trick:

   type T is limited record
      Self : access T'Class := T'Unchecked_Access;
      ...
   end record;

>>>>> That
>>>>> forces the representation to be compatible. You could change that for
>>>>> by-copy types (although that would have run-time compatibility issues 
>>>>> for controlled objects),
>>>>
>>>> Controlled objects are tagged, hence no change here.
>>>
>>> A component is an object; I'm talking about untagged objects with 
>>> controlled components here.
>>
>> No change either. If a by-copy object passed by value has a controlled
>> component that component is copied-in and out using Adjust and
>> Finalization.
> 
> That's the problem. If that is done in existing code, you have an 
> incompatibility (because the same code does something different now).

Why? If that type is by-copy then this is how it must work already. If it
is by-reference then nothing changes either.

>>>>> but you can't change that for types that have no copy
>>>>> operation (like tasks and protected objects). So how to do you 
>>>>> implement
>>>>> them? Array of task is an untagged type, too, and it certainly should 
>>>>> be
>>>>> able to use 'Class.
>>>>
>>>> Sure. T'Class will be a referential object when T is untagged 
>>>> by-reference
>>>> type. It will consist of the type tag and a *pointer* to the specific
>>>> object (not much different from 4.1.5), and from view conversions ether,
>>>> though formally a new object.
>>>>
>>>> When T is by-copy, T'Class is the type tag + a copy of T.
>>>
>>> Wow! And this is supposed to be a *simplification*??? :-)
>>
>> Yes. It is much simpler to view tagged types as a special case [definite
>> representation constraint] of a more general model that encompasses all
>> types.
> 
> A more general model that is many times more complex than the existing 
> model. What exactly is being simplified?

You will have all strings in one hierarchy. All characters in another. All
integer types in third. Tagged types described using a footnote.

>>>>>> The whole idea is not to inherit irrelevant representations!
>>>>>
>>>>> I don't see the problem here; if Root_String is an abstract tagged 
>>>>> type,
>>>>
>>>> Java interfaces will not work for characters/strings. No need even to 
>>>> try it.
>>>
>>> Java interfaces will not work for anything. No need to even try. :-) And
>>> who's talking about Java, anyway?
>>
>> You want strings hierarchy of one level depth. That won't work.
> 
> I don't even know what you mean by "one level depth", but I've already 
> prototyped such a string type and it works fine -- better than the existing 
> types.

You want to derive each string type straight from Root_String.

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



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

* Re: Is this expected behavior or not
  2013-04-04  8:26                                                                                                         ` Dmitry A. Kazakov
@ 2013-04-04 20:31                                                                                                           ` Randy Brukardt
  2013-04-05  9:57                                                                                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-04 20:31 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1fmcdkj58brky.bjedt0pr39cd$.dlg@40tude.net...
> On Wed, 3 Apr 2013 19:04:24 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1gkxiwepaxvtt$.u3ly33rbwthf.dlg@40tude.net...
>
>>> If you have more than one controlled argument/result of the same type,
>>> that makes it a multi-method. The natural consequence of this is that 
>>> all
>>> possible combinations of types from the hierarchy are specific bodies to
>>> inherit/override. In Ada 95 only the bodies when all types are same can 
>>> be
>>> overridden. Statically the compiler prevents calls to mixed types 
>>> bodies,
>>> but they nevertheless exist and can be reached through dispatch. In that
>>> case it works as if the body were "rase Constraint_Error." This hack 
>>> won't
>>> work for &, =, <, <= etc. Those require almost all combinations to work.
>>
>> I see where you are coming from, but I don't agree with any of it on a
>> fundamental level: mixing types in operations is virtually always an 
>> error
>> (either a real mistake or a design error).
>
> How is it an error to compare String and Wide_String?

The same way it is an error to compare a float and an integer. You could 
make a rule with somewhat sensible results, but it's a bad idea because it 
hides more errors than it simplifies correct code.

>> I don't believe that these use cases are at all common. I don't recall 
>> any
>> such cases in Claw, for example, which uses Ada 95 inheritance 
>> extensively.
>
> That is because GUI does not require dyadic operations at all. There are
> few cases for MD though. E.g.
>
>   procedure Render (Surface : in out Device_Type; Shape : Geometric_Type);
>
> And of course:
>
>   procedure Set_Text (Control : Edit_Box; Text : Root_String_Type);

This is clearly class-wide:

   procedure Set_Text (Control : Edit_Box; Text : Root_String_Type'Class);

The implementation would use the constructor for Text to create the value, 
so it's straightforward to implement. (The Edit_Box has to have some 
particular representation for text, even if the result does not.)

>>> The only pattern that sometimes works is recursive cascaded dispatch. 
>>> That
>>> is when you make one argument controlled and another class-wide.
>>
>> Gosh, that's what I was talking from the beginning.
>
> It works only with dyadic operations, procedures or else functions
> returning an alien type.

Which is 95% of the cases that you would want.

>>> I used it for "=" and "<" multi-method operations of the target type
>>> hierarchy of
>>> smart pointers. I needed this to be able to have ordered collections of
>>> smart pointers to such objects when pointers are ordered by the objects
>>> they point to. It is extremely tedious, involves recursive calls and
>>> explicit tag comparisons for ancestry. It won't work with for operations
>>> like &, which has two arguments and the result.
>>
>> You don't want mixed operations in cases like "&", ever.
>
> Non-starter for strings.

Mixed operations are almost always a non-starter for any type.

>> It simply doesn't
>> make any sense from a resolution prespective. You want to fix resolution 
>> by
>> introducing a set of very complex preference rules.
>
> Actually I want these rules defined by the programmer. And resolution is
> only the issue with the operations returning the type, e.g. literals. One
> cannot have both covariant result factories and multi-method operations. 
> If
> I ran the circus I would try to define rules that would prohibit
> declaration of potentially conflicting operations, like:
>
>   type T is ...; -- Untagged class
>
>   function Generator return T;
>   function "=" (L, R  : T) return Boolean;
>
> This should be an error unless preference rules defined by the programmer
> for T.

I have no idea how that could work. Resolution is a very complex business 
both to define and to implement. It's hopeless for ordinary users to be able 
to make sense of it, and the implementation seems like it would be 
impossible. Moreover, unbounded preference rules also means unbounded 
maintenance headaches (preference rules almost always causing bad behavior). 
Generally, it's the lack of overloading, not the provision for more, that 
causes the trouble.

...
>> Interfaces alone are worthless. The only thing that makes inheritance 
>> worth
>> the effort is the ability to share implementations.
>
> Implementation /= representations. You can share class-wide operations and
> inherit primitive operations without sharing the representation.

You can, but it's virtually worthless to do so. It's simply too much work 
for any supposed benefit. (Not that I expect you to believe this.)


>>> Anyway, the point is, that the compiler shall inherit a body IF AND ONLY 
>>> IF
>>> it knows that this would be safe to do. That is the following cases:
>>>
>>> 1. Any operation when the representation is same
>>>
>>> 2. In-operation when the representation is extension or constraint
>>>
>>> 3. Out-operation when the representation is generalization (lifted
>>> constraint) [Ada does not have this, as an example consider extension of
>>> an enumeration type]
>>>
>>> 4. User-defined conversion defined, programmer's responsibility [Ada 
>>> does
>>> not have this]
>>>
>>> On top of that come pre- and post-conditions which may in their turn
>>> disallow inheritance of the body.
>>
>> Besides being incompatible,
>
> ? I merely explained why Ada 95 design choice was right [#2].
>
>> I suspect that this would just be too complex
>> for the average Ada user to understand.
>
> It need not to be understood. The programmer will be asked to override
> operation or else to make type abstract, just as Ada 95 did.

You have to avoid this sort of thing, the Ada 95 effects make it absolutely 
necessary to avoid functions returning a controlled type, else creating 
extensions is so hard that no one will do it. And to avoid them you have to 
understand it.

...
>>>>>> The only way to implement those is
>>>>>> via some sort of dispatching, and the need poisons the possibility of
>>>>>> omitting tags, even for "specific" operations.
>>>>>
>>>>> I don't understand where you get this. The model is exactly the model 
>>>>> of
>>>>> tagged types, but without specific objects required to keep the tag. 
>>>>> The
>>>>> only thing it influences is view conversions between T and T'Class.
>>>>> Nothing else is changed.
>>>>
>>>> When you dispatch to an inherited routine, you directly call that 
>>>> routine
>>>> with the operands view converted (which cannot make copies in the 
>>>> general
>>>> case).
>>>
>>> For by-copy types dispatching call will be copy-in / copy-out. The
>>> representation of T'Class is tag + value. Tag is stripped, value passed
>>> through.
>>>
>>> For by-reference untagged types dispatching call will pass the 
>>> reference.
>>> The representation of T'Class is tag + pointer. Tag is stripped, 
>>> reference
>>> passed through.
>>
>> What about the majority of types which are neither By-Copy nor 
>> By-Reference?
>> Such types allow the compiler to chose how they're passed, and that would
>> seem to be a huge problem for this model.
>
> Not at all, the compiler is free to choose, so it must. [I don't consider
> schizophrenic compilers choosing one way and doing in another. That does
> not work with any model.]

It doesn't work for portability reasons for some compilers to call Adjust 
during the evaluation of parameters and other compilers to not call Adjust. 
It would make performance wildly variable and possibly cause bugs (if the 
program unintentionally depended on one or the other.

>> You'd have to forcibly specify one
>> or the other for all types, which is certain to be incompatible with
>> existing implementations.
>
> The compiler vendor simply follows the choice he made before.

Thus making most Ada code non-portable. That's a great idea. :-(

>> It strikes me that the model of stripping tags means that type conversion 
>> of
>> an object to a class-wide type would effectively change the tag (if the
>> routine was inherited or called by a conversion of an operand).
>
> Yes, re-dispatch is a broken thing. Don't do it, because it is ambiguous 
> in
> general case when objects do not have an identity. By-copy scalar types 
> are
> such things. There is nothing which could distinguish Integer 13 from
> Long_Integer 13 except the context. Once you dispatched that information 
> is
> lost. There is no way back.
>
>> That would
>> mean that the behavior of such a conversion would be very different for 
>> an
>> untagged type and for a tagged type.
>
> Not different. It is just so that tagged types per design have type
> identity. Other types simply don't have it.

Objects of limited types are always assumed to have an identity; that's why 
they can't be copied.

...
>>> No change either. If a by-copy object passed by value has a controlled
>>> component that component is copied-in and out using Adjust and
>>> Finalization.
>>
>> That's the problem. If that is done in existing code, you have an
>> incompatibility (because the same code does something different now).
>
> Why? If that type is by-copy then this is how it must work already. If it
> is by-reference then nothing changes either.

Because currently, you don't call Adjust/Finalize for a type conversion. And 
it would have to be specified whether a type is by-copy or by-reference (it 
could not be left to the compiler with these rules, as I previously 
mentioned) -- that means compilers would have to change in some cases.

...
>> A more general model that is many times more complex than the existing
>> model. What exactly is being simplified?
>
> You will have all strings in one hierarchy. All characters in another. All
> integer types in third. Tagged types described using a footnote.

That's already true, you just don't have inheritance of operations for these 
hierarchies. So exactly what you are simplifying but introducing this whole 
new notion of type cloning, this new notion of when you must override 
routines, and so on??

>>>>>>> The whole idea is not to inherit irrelevant representations!
>>>>>>
>>>>>> I don't see the problem here; if Root_String is an abstract tagged
>>>>>> type,
>>>>>
>>>>> Java interfaces will not work for characters/strings. No need even to
>>>>> try it.
>>>>
>>>> Java interfaces will not work for anything. No need to even try. :-) 
>>>> And
>>>> who's talking about Java, anyway?
>>>
>>> You want strings hierarchy of one level depth. That won't work.
>>
>> I don't even know what you mean by "one level depth", but I've already
>> prototyped such a string type and it works fine -- better than the 
>> existing
>> types.
>
> You want to derive each string type straight from Root_String.

Yes, or from related ones. There is no significant value to doing anything 
else - as you point out, if you can inherit the operations, the 
representations have to be compatible. So there is nothing useful you can do 
with multiple levels. And if you want pure inheritance of (non-string) 
interfaces, then mix in some interfaces with your types (forget normal 
derivation in that case).

                                   Randy.




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

* Re: Is this expected behavior or not
  2013-04-04 20:31                                                                                                           ` Randy Brukardt
@ 2013-04-05  9:57                                                                                                             ` Dmitry A. Kazakov
  2013-04-05 12:45                                                                                                               ` Stefan.Lucks
  2013-04-06  1:20                                                                                                               ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-05  9:57 UTC (permalink / raw)


On Thu, 4 Apr 2013 15:31:23 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1fmcdkj58brky.bjedt0pr39cd$.dlg@40tude.net...
>> On Wed, 3 Apr 2013 19:04:24 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:1gkxiwepaxvtt$.u3ly33rbwthf.dlg@40tude.net...
>>
>>>> If you have more than one controlled argument/result of the same type,
>>>> that makes it a multi-method. The natural consequence of this is that all
>>>> possible combinations of types from the hierarchy are specific bodies to
>>>> inherit/override. In Ada 95 only the bodies when all types are same can 
>>>> be overridden. Statically the compiler prevents calls to mixed types bodies,
>>>> but they nevertheless exist and can be reached through dispatch. In that
>>>> case it works as if the body were "rase Constraint_Error." This hack 
>>>> won't work for &, =, <, <= etc. Those require almost all combinations to work.
>>>
>>> I see where you are coming from, but I don't agree with any of it on a
>>> fundamental level: mixing types in operations is virtually always an 
>>> error (either a real mistake or a design error).
>>
>> How is it an error to compare String and Wide_String?
> 
> The same way it is an error to compare a float and an integer.

It is not same. R and Z are different mathematical constructs. Unicode
strings, all of them, are semantically exactly same except for encoding
[representation] and constraints put on the code point set.

> You could 
> make a rule with somewhat sensible results, but it's a bad idea because it 
> hides more errors than it simplifies correct code.

If that were so, you should not have them in the same hierarchy. You want
to have one class in order to share operations like Put_Line. These
operations are far more questionable than comparison. If you challenge
comparison, you should not do Put_Line either.

You design decisions are motivated by compiler implementation issues not by
the actual properties of strings.

>>> I don't believe that these use cases are at all common. I don't recall 
>>> any such cases in Claw, for example, which uses Ada 95 inheritance 
>>> extensively.
>>
>> That is because GUI does not require dyadic operations at all. There are
>> few cases for MD though. E.g.
>>
>>   procedure Render (Surface : in out Device_Type; Shape : Geometric_Type);
>>
>> And of course:
>>
>>   procedure Set_Text (Control : Edit_Box; Text : Root_String_Type);
> 
> This is clearly class-wide:
> 
>    procedure Set_Text (Control : Edit_Box; Text : Root_String_Type'Class);
> 
> The implementation would use the constructor for Text to create the value, 
> so it's straightforward to implement. (The Edit_Box has to have some 
> particular representation for text, even if the result does not.)

Now this:

    function Get_Text (Control : Edit_Box) return Root_String_Type;

>>>> The only pattern that sometimes works is recursive cascaded dispatch. 
>>>> That is when you make one argument controlled and another class-wide.
>>>
>>> Gosh, that's what I was talking from the beginning.
>>
>> It works only with dyadic operations, procedures or else functions
>> returning an alien type.
> 
> Which is 95% of the cases that you would want.

No more than 20-30% actually.

>>>> I used it for "=" and "<" multi-method operations of the target type
>>>> hierarchy of
>>>> smart pointers. I needed this to be able to have ordered collections of
>>>> smart pointers to such objects when pointers are ordered by the objects
>>>> they point to. It is extremely tedious, involves recursive calls and
>>>> explicit tag comparisons for ancestry. It won't work with for operations
>>>> like &, which has two arguments and the result.
>>>
>>> You don't want mixed operations in cases like "&", ever.
>>
>> Non-starter for strings.
> 
> Mixed operations are almost always a non-starter for any type.

Mixed operations are a must for all algebraic types and all string types.
Ada 83 had it mixed from the start, e.g. Universal_Integer vs. Integer. Ada
95 added mixed operations for access types.

Without mixed operations, hierarchies of scalar type, strings, access types
were useless.

>> It need not to be understood. The programmer will be asked to override
>> operation or else to make type abstract, just as Ada 95 did.
> 
> You have to avoid this sort of thing,

You cannot avoid it, because there is no way the compiler could define it
semantically correct.

> the Ada 95 effects make it absolutely 
> necessary to avoid functions returning a controlled type, else creating 
> extensions is so hard that no one will do it.

I don't know where you get that idea. I never had any problem with abstract
factories. Actual problem is fighting senseless limitations imposed by the
language, which makes design very hard as you never know if the derived
type would be possible to construct. Limited aggregates/functions, broken
initialization/finalization, leaking separation of specification and
implementation, missing initialization/finalization of class-wides etc.
That makes it difficult. 

>> Not at all, the compiler is free to choose, so it must. [I don't consider
>> schizophrenic compilers choosing one way and doing in another. That does
>> not work with any model.]
> 
> It doesn't work for portability reasons for some compilers to call Adjust 
> during the evaluation of parameters and other compilers to not call Adjust.

When the type neither specified as either by-reference nor as by-value, it
shall be exactly this way. I don't understand why this is relevant.
 
> It would make performance wildly variable and possibly cause bugs (if the 
> program unintentionally depended on one or the other.

Yes, the language permits compilers implemented poorly, and?

>>> You'd have to forcibly specify one
>>> or the other for all types, which is certain to be incompatible with
>>> existing implementations.
>>
>> The compiler vendor simply follows the choice he made before.
> 
> Thus making most Ada code non-portable.

No more than they already are. The program that exploits certain type of
parameter passing for a type which is not specified as either by value or
by reference is erroneous. End of story.

>>> It strikes me that the model of stripping tags means that type conversion 
>>> of an object to a class-wide type would effectively change the tag (if the
>>> routine was inherited or called by a conversion of an operand).
>>
>> Yes, re-dispatch is a broken thing. Don't do it, because it is ambiguous 
>> in general case when objects do not have an identity. By-copy scalar types 
>> are such things. There is nothing which could distinguish Integer 13 from
>> Long_Integer 13 except the context. Once you dispatched that information 
>> is lost. There is no way back.
>>
>>> That would
>>> mean that the behavior of such a conversion would be very different for 
>>> an untagged type and for a tagged type.
>>
>> Not different. It is just so that tagged types per design have type
>> identity. Other types simply don't have it.
> 
> Objects of limited types are always assumed to have an identity;

No. E.g. task and protected types lack type identity. Only tagged types
have type identity.

Note that type identity /= object identity (e.g. machine address where the
object resides).

>>>> No change either. If a by-copy object passed by value has a controlled
>>>> component that component is copied-in and out using Adjust and
>>>> Finalization.
>>>
>>> That's the problem. If that is done in existing code, you have an
>>> incompatibility (because the same code does something different now).
>>
>> Why? If that type is by-copy then this is how it must work already. If it
>> is by-reference then nothing changes either.
> 
> Because currently, you don't call Adjust/Finalize for a type conversion. And 
> it would have to be specified whether a type is by-copy or by-reference (it 
> could not be left to the compiler with these rules, as I previously 
> mentioned) -- that means compilers would have to change in some cases.

No, it will stay exactly as it is now. Type conversion is irrelevant.

>>> A more general model that is many times more complex than the existing
>>> model. What exactly is being simplified?
>>
>> You will have all strings in one hierarchy. All characters in another. All
>> integer types in third. Tagged types described using a footnote.
> 
> That's already true, you just don't have inheritance of operations for these 
> hierarchies. So exactly what you are simplifying but introducing this whole 
> new notion of type cloning, this new notion of when you must override 
> routines, and so on??

I don't introduce anything Ada 83 or 95 do not have already. I want to lift
meaningless language limitations which lead to silly design decisions like
inability to concatenate or compare two strings.

>> You want to derive each string type straight from Root_String.
> 
> Yes, or from related ones. There is no significant value to doing anything 
> else - as you point out, if you can inherit the operations, the 
> representations have to be compatible. So there is nothing useful you can do 
> with multiple levels.

Encoding!

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

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

* Re: Is this expected behavior or not
  2013-04-05  9:57                                                                                                             ` Dmitry A. Kazakov
@ 2013-04-05 12:45                                                                                                               ` Stefan.Lucks
  2013-04-05 12:49                                                                                                                 ` Stefan.Lucks
  2013-04-05 14:36                                                                                                                 ` Dmitry A. Kazakov
  2013-04-06  1:20                                                                                                               ` Randy Brukardt
  1 sibling, 2 replies; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-05 12:45 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 2585 bytes --]

On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:

>>> How is it an error to compare String and Wide_String?
>>
>> The same way it is an error to compare a float and an integer.
>
> It is not same. R and Z are different mathematical constructs.

Sure! This is different from string types, where the distinction between 
String, Wide_String, Wide_Wide_String, and whatever comes next has 
historical reasons. It makes mixing narrow, Wide_ and Wide_Wide_ Strings 
worse than mixing reals and integers.

> Unicode strings, all of them, are semantically exactly same except for 
> encoding [representation] and constraints put on the code point set.

N is a subset of Z is a subset of Q is a subset of R.

Furthermore, each "X is a subset of Y" relationship implies that any 
operation possible in X is also possible in Y, including comparisons.

How are generalised strings simpler than generalised numbers?

> Mixed operations are a must for all algebraic types and all string types.

Well, Ada does make a clear distinction between Universal_Integer and 
Universal_Real. So why should it work for String types?

> Ada 83 had it mixed from the start, e.g. Universal_Integer vs. Integer.

Ada (all Adas from 83 to 2012) had two *different* algebraic root types.

In any cases, there are good reasons why a program has sometimes to mix
real and natural numbers. But what reasons would you have to actually mix 
narrow, Wide_ and Wide_Wide_ Strings? That is bad program design, anyway!

It is error-prone low-level programming, quite similar to the C-style of 
using memory addresses and pointer arithmetic. If you *have* to do it, 
perhaps because you have to support some legacy interfaces, with different 
string types, you better hide the input/output stuff in some low-level 
packages, and use a single kind of string in your application logic 
(perhaps Wide_Wide_String, if the memory isn't too small).

Of course, a single common root type for String, Bounded_String and 
Unbounded_String would come handy -- similarly another root type for the 
Wide_ and yet another for the Wide_Wide_ family. But note that not even 
Universal_Integer does provide such a root type! The Standard(-Library) 
did not even define any Bounded_Integer or Unbounded_Integer types to deal 
with huge integers, in contrast to strings.




------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-05 12:45                                                                                                               ` Stefan.Lucks
@ 2013-04-05 12:49                                                                                                                 ` Stefan.Lucks
  2013-04-05 14:19                                                                                                                   ` Dmitry A. Kazakov
  2013-04-05 14:36                                                                                                                 ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-05 12:49 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 857 bytes --]

On Fri, 5 Apr 2013, Stefan.Lucks@uni-weimar.de wrote:

> On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:
>
>> Unicode strings, all of them, are semantically exactly same except for 
>> encoding [representation] and constraints put on the code point set.
>
> N is a subset of Z is a subset of Q is a subset of R.
>
> Furthermore, each "X is a subset of Y" relationship implies that any 
> operation possible in X is also possible in Y, including comparisons.

What I meant to write:

Numbers, naturals, integers, rationals and reals, are semantically exactly 
same except for encoding [representation] and constraints.



------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-05 12:49                                                                                                                 ` Stefan.Lucks
@ 2013-04-05 14:19                                                                                                                   ` Dmitry A. Kazakov
  2013-04-05 14:44                                                                                                                     ` Stefan.Lucks
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-05 14:19 UTC (permalink / raw)


On Fri, 5 Apr 2013 14:49:41 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Fri, 5 Apr 2013, Stefan.Lucks@uni-weimar.de wrote:
> 
>> On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:
>>
>>> Unicode strings, all of them, are semantically exactly same except for 
>>> encoding [representation] and constraints put on the code point set.
>>
>> N is a subset of Z is a subset of Q is a subset of R.

Depends on construction. The proper statement is that Q has a subset
equivalent to Z and R has a subset equivalent to Q.

>> Furthermore, each "X is a subset of Y" relationship implies that any 
>> operation possible in X is also possible in Y, including comparisons.
> 
> What I meant to write:
> 
> Numbers, naturals, integers, rationals and reals, are semantically exactly 
> same except for encoding [representation] and constraints.

A quite common misunderstanding. Structure such as field is not same as a
subset. To see the difference between R and Z consider the following
predicate:

   forall x in S exists y such as x=1/y  [multiplicative inverse]

This is true for S=R and false for S=Z.

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


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

* Re: Is this expected behavior or not
  2013-04-05 12:45                                                                                                               ` Stefan.Lucks
  2013-04-05 12:49                                                                                                                 ` Stefan.Lucks
@ 2013-04-05 14:36                                                                                                                 ` Dmitry A. Kazakov
  2013-04-05 15:16                                                                                                                   ` Stefan.Lucks
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-05 14:36 UTC (permalink / raw)


On Fri, 5 Apr 2013 14:45:55 +0200, Stefan.Lucks@uni-weimar.de wrote:

> But what reasons would you have to actually mix 
> narrow, Wide_ and Wide_Wide_ Strings?

What is at least one reason to distinguish them?

Once answered, please name a reason to distinguish UTF-16, UTF-8, UCS-2 etc
strings in assignment, comparison, concatenation.

There is none. Ugly design of Unbounded_String proved that.

All differences are motivated by implementation details and related to the
string origin or its consumer.

Semantically all strings are nothing but sequences of code points.

And, again, it is already *mixed* in Ada. "abc" is overloaded String,
Wide_String, Wide_Wide_String.

Furthermore, very idea of new string design is to mix it even more than it
was before in order to get rid of the mess of I/O package multiplying like
cockroaches.

The difference between Randy and me, is that he wants to scrap all
operations Ada 83 strings had. Since this would be clearly incompatible
with existing programs, he wants to add them as completely new types, as if
we had not enough string types in the language already.

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


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

* Re: Is this expected behavior or not
  2013-04-05 14:19                                                                                                                   ` Dmitry A. Kazakov
@ 2013-04-05 14:44                                                                                                                     ` Stefan.Lucks
  2013-04-05 16:11                                                                                                                       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-05 14:44 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 1252 bytes --]

On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:

>> Numbers, naturals, integers, rationals and reals, are semantically exactly
>> same except for encoding [representation] and constraints.
>
> A quite common misunderstanding. Structure such as field is not same as a
> subset. To see the difference between R and Z consider the following
> predicate:
>
>   forall x in S exists y such as x=1/y  [multiplicative inverse]
>
> This is true for S=R and false for S=Z.

Fair enough!

But the same is true for N and Z: every in Z has an additive inverse, but 
not every number in N. If the non-existence of a multiplicative inverse 
would justify different root types for Z and R, why should the 
non-existence of an additive inverse not justify different root types for 
N and Z (Universal_Positive versus Universal_Integer).

As it turns out, the fact that Naturals and Positives have the same 
representation as Integers, while Float has a different one, matters more 
than any "mathematical structure" ...





------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-05 14:36                                                                                                                 ` Dmitry A. Kazakov
@ 2013-04-05 15:16                                                                                                                   ` Stefan.Lucks
  2013-04-05 16:29                                                                                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-05 15:16 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 1816 bytes --]

On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:

> On Fri, 5 Apr 2013 14:45:55 +0200, Stefan.Lucks@uni-weimar.de wrote:
>
>> But what reasons would you have to actually mix
>> narrow, Wide_ and Wide_Wide_ Strings?
>
> What is at least one reason to distinguish them?

I agree with you that there is no reason to distinguish between them. The 
entire distinction narrow, Wide_ and Wide_Wide_ Strings (and Characters) 
is a historical artifact, no more, no less.

But if there is no reason to disting between them -- there is no reason to 
mix them either!

Right now, the best you can do if you really have to use different of 
these String types is the following:
   1. convert everything into a single type (probably Wide_Wide_String),
   2. do your work.
   3. and convert back (if you really have to).

> Once answered, please name a reason to distinguish UTF-16, UTF-8, UCS-2 etc
> strings in assignment, comparison, concatenation.

I agree, there is none. Which is precicely why one should not need any 
mixed-representation operations.

> The difference between Randy and me, is that he wants to scrap all
> operations Ada 83 strings had. Since this would be clearly incompatible
> with existing programs, he wants to add them as completely new types, as if
> we had not enough string types in the language already.

I think, I agree with Randy here. The old bunch of strings are a mess, 
that has historically evolved and is far beyond repair. Trying to repair 
it by adding support for mixed operations gives birth to a gazillion of 
new cockroaches.


------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-05 14:44                                                                                                                     ` Stefan.Lucks
@ 2013-04-05 16:11                                                                                                                       ` Dmitry A. Kazakov
  2013-04-05 19:02                                                                                                                         ` Stefan.Lucks
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-05 16:11 UTC (permalink / raw)


On Fri, 5 Apr 2013 16:44:53 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:
> 
>>> Numbers, naturals, integers, rationals and reals, are semantically exactly
>>> same except for encoding [representation] and constraints.
>>
>> A quite common misunderstanding. Structure such as field is not same as a
>> subset. To see the difference between R and Z consider the following
>> predicate:
>>
>>   forall x in S exists y such as x=1/y  [multiplicative inverse]
>>
>> This is true for S=R and false for S=Z.
> 
> Fair enough!
> 
> But the same is true for N and Z: every in Z has an additive inverse, but 
> not every number in N. If the non-existence of a multiplicative inverse 
> would justify different root types for Z and R, why should the 
> non-existence of an additive inverse not justify different root types for 
> N and Z (Universal_Positive versus Universal_Integer).

That depends solely on the application domain. When numbers are used as
indices (ordinals) they require certain properties, e.g. to form an
additive group. Other application domains require other properties. That is
why the language shall not dictate which interfaces (and thus properties) a
given type has to implement.

> As it turns out, the fact that Naturals and Positives have the same 
> representation as Integers, while Float has a different one, matters more 
> than any "mathematical structure" ...

Nope, representation never matter. Employee ID and task ID may have same
representation. That does not mean anything. Nominal type equivalence was a
corner stone of Ada design.

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


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

* Re: Is this expected behavior or not
  2013-04-05 15:16                                                                                                                   ` Stefan.Lucks
@ 2013-04-05 16:29                                                                                                                     ` Dmitry A. Kazakov
  2013-04-05 19:55                                                                                                                       ` Stefan.Lucks
  2013-04-06  1:38                                                                                                                       ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-05 16:29 UTC (permalink / raw)


On Fri, 5 Apr 2013 17:16:59 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:
> 
>> On Fri, 5 Apr 2013 14:45:55 +0200, Stefan.Lucks@uni-weimar.de wrote:
>>
>>> But what reasons would you have to actually mix
>>> narrow, Wide_ and Wide_Wide_ Strings?
>>
>> What is at least one reason to distinguish them?
> 
> I agree with you that there is no reason to distinguish between them. The 
> entire distinction narrow, Wide_ and Wide_Wide_ Strings (and Characters) 
> is a historical artifact, no more, no less.
> 
> But if there is no reason to disting between them -- there is no reason to 
> mix them either!

Sorry, but it cannot be both.

> Right now, the best you can do if you really have to use different of 
> these String types is the following:
>    1. convert everything into a single type (probably Wide_Wide_String),
>    2. do your work.
>    3. and convert back (if you really have to).

This is how the compiler could implement the interface inherited from the
root string type, e.g. from Wide_Wide_String.

But that is an implementation detail. The problem is in resolution of mixed
operations *inevitably* emerging from putting strings under the same roof.

Wether you inherit an implementation from Wide_Wide_String and compose it
with a conversion forth and/or back to String or else override it with a
tailored implementation is not the core problem. The problem is that Ada
does not support multi-methods needed for this. That literals generate
uncontrollable ambiguities. These problems are to address.

>> Once answered, please name a reason to distinguish UTF-16, UTF-8, UCS-2 etc
>> strings in assignment, comparison, concatenation.
> 
> I agree, there is none. Which is precicely why one should not need any 
> mixed-representation operations.

How so? Apart from comparisons and concatenation. Consider
Ada.Text_IO.Create. It has name a string and content. You tell us that it
is not necessary to be able to open an UTF-8 file which name is UTF-16?
Blame Microsoft.

>> The difference between Randy and me, is that he wants to scrap all
>> operations Ada 83 strings had. Since this would be clearly incompatible
>> with existing programs, he wants to add them as completely new types, as if
>> we had not enough string types in the language already.
> 
> I think, I agree with Randy here. The old bunch of strings are a mess,

There is nothing wrong with them except for being not in the same class.
[Literals could be done better]
 
> that has historically evolved and is far beyond repair. Trying to repair 
> it by adding support for mixed operations gives birth to a gazillion of 
> new cockroaches.

They tried once, see Unbounded_String. They tried twice, see bounded
strings. This is an inherently flawed approach.

Furthermore what Randy proposes will actually be worse than pitiful
Unbounded_String. For them you could at least do this:

   type Relative_File_Path is new Unbounded_String;
   type Absolute_File_Path is new Unbounded_String;

You could not do that for tagged strings.

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


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

* Re: Is this expected behavior or not
  2013-04-05 16:11                                                                                                                       ` Dmitry A. Kazakov
@ 2013-04-05 19:02                                                                                                                         ` Stefan.Lucks
  2013-04-05 19:34                                                                                                                           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-05 19:02 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 2239 bytes --]

On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:

> On Fri, 5 Apr 2013 16:44:53 +0200, Stefan.Lucks@uni-weimar.de wrote:

>> But the same is true for N and Z: every in Z has an additive inverse, but
>> not every number in N. If the non-existence of a multiplicative inverse
>> would justify different root types for Z and R, why should the
>> non-existence of an additive inverse not justify different root types for
>> N and Z (Universal_Positive versus Universal_Integer).
>
> That depends solely on the application domain.

Ada is a general-purpose language. We are discussing Ada's type concept 
and not any specific application, so there is not "the application domain" 
anything could possibly depend on.

>> As it turns out, the fact that Naturals and Positives have the same
>> representation as Integers, while Float has a different one, matters more
>> than any "mathematical structure" ...
>
> Nope, representation never matter. Employee ID and task ID may have same
> representation. That does not mean anything. Nominal type equivalence was a
> corner stone of Ada design.

Dmitry, I admire your ability to make some correct claim, being out of 
topic, and then pretending that this claim makes your point! ;-)

Sure, one of the main strengths of Ada from its beginning is allowing the 
programmer to define different and intentionally incompatible types with 
identical representations.

But you are actually proposing the opposite: Making different types with 
different representations intentionally compatible by introducing some 
universal super-type and then formally deriving the different types from 
the super-type.

Actually another corner stone of Ada has been the language designers' 
reluctance to introduce implicit conversions between types with different 
representations. Sure, some cases where implicit conversions take place 
exist, but only very few. One example is the conversion of constants of 
type Universal_Something into the right type.



------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-05 19:02                                                                                                                         ` Stefan.Lucks
@ 2013-04-05 19:34                                                                                                                           ` Dmitry A. Kazakov
  2013-04-05 20:23                                                                                                                             ` Stefan.Lucks
  2013-04-05 20:38                                                                                                                             ` Stefan.Lucks
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-05 19:34 UTC (permalink / raw)


On Fri, 5 Apr 2013 21:02:43 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:
> 
>> On Fri, 5 Apr 2013 16:44:53 +0200, Stefan.Lucks@uni-weimar.de wrote:
> 
>>> But the same is true for N and Z: every in Z has an additive inverse, but
>>> not every number in N. If the non-existence of a multiplicative inverse
>>> would justify different root types for Z and R, why should the
>>> non-existence of an additive inverse not justify different root types for
>>> N and Z (Universal_Positive versus Universal_Integer).
>>
>> That depends solely on the application domain.
> 
> Ada is a general-purpose language.

Yes <=> Ada can be used for most application domains.

> We are discussing Ada's type concept 
> and not any specific application, so there is not "the application domain" 
> anything could possibly depend on.

We are discussing deficiencies of Ada type system, unable to capture
relations between domain specific entities modeled as objects and types.

E.g. few built-in numeric types, which are supposed to fit everything and
expectedly fail, because predefined numbers have properties you might not
need and miss ones you do need. The Op's subtype Prim was a perfect example
of such a failure. Prime numbers are neither additive nor multiplicative.
It is not a group. Yet Prime inherited the interface of a group from base
type (Positive) and there is no way to prohibit this. It also inherited the
order of Positives ('Succ), which is not one of Prime, and, again, there is
no language means for fix that.

> Sure, one of the main strengths of Ada from its beginning is allowing the 
> programmer to define different and intentionally incompatible types with 
> identical representations.

How is representation relevant here? Two incompatible types are
incompatible per programmer's wish, whichever representation they might
have. Representation is an implementation detail.

> But you are actually proposing the opposite: Making different types with 
> different representations intentionally compatible by introducing some 
> universal super-type and then formally deriving the different types from 
> the super-type.

No, I insist that it is up to the programmer to decide whether two types to
become compatible (relative) or not. Character and Wide_Character are
evidently relative. Velocity and Acceleration are not (considering
assignment operation and additive group operations). They are relative
considering multiplication. This is why multiple inheritance is a key
issue.

> Actually another corner stone of Ada has been the language designers' 
> reluctance to introduce implicit conversions between types with different 
> representations.

I disagree. They wanted to prevent the mess of PL/1 where *arbitrary*
conversions were applied to semantically unrelated types. Types like
Character and Wide_Character are semantically related. Conversion from one
to another is perfectly well defined.

> Sure, some cases where implicit conversions take place 
> exist, but only very few. One example is the conversion of constants of 
> type Universal_Something into the right type.

It makes sense in all cases where types are related. This is simply the
definition of a type S being a subtype of T <=> S is substitutable for T.
If representations are different the substitution is done per conversion.
Not a rocket science, really.

And it is all up to the programmer to tell the compiler that S must be
considered a subtype of T, whatever representation both might have is not
language's business.

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

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

* Re: Is this expected behavior or not
  2013-04-05 16:29                                                                                                                     ` Dmitry A. Kazakov
@ 2013-04-05 19:55                                                                                                                       ` Stefan.Lucks
  2013-04-06  1:45                                                                                                                         ` Randy Brukardt
  2013-04-06  7:54                                                                                                                         ` Dmitry A. Kazakov
  2013-04-06  1:38                                                                                                                       ` Randy Brukardt
  1 sibling, 2 replies; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-05 19:55 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 4534 bytes --]

On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:

> On Fri, 5 Apr 2013 17:16:59 +0200, Stefan.Lucks@uni-weimar.de wrote:

>> I agree with you that there is no reason to distinguish between them. The
>> entire distinction narrow, Wide_ and Wide_Wide_ Strings (and Characters)
>> is a historical artifact, no more, no less.
>>
>> But if there is no reason to disting between them -- there is no reason to
>> mix them either!
>
> Sorry, but it cannot be both.

No, if you mix them, you must distinguish them. At least, when 
implementing your own multi-method, such as

   function Longest_Common_Substring(S1, S2: Universal_String)
                                    return Universal_String;
                                              -- maybe "is abstract";

Either Universal_String is abstract, then so would be this multi-method, 
and you would to override it n^3 times, when supporting n different string 
types. Or you can actually have objects of type Universal_String, but then 
using this method without making explicit conversions means a whole new 
bunch of implicit conversions.

One problem with implicit conversions is that Strings don't "know" their 
encoding (Is it UTF-8? Or ISO-Latin-1? Or ...?), so you don't even have 
the information you need to perform the conversion. Which is why you need 
to make explicit conversions.

And then it is not a big leap to say "convert everything into my favourite 
kind of string, then call my method, and then convert the result back".

> Consider Ada.Text_IO.Create. It has name a string and content. You tell 
> us that it is not necessary to be able to open an UTF-8 file which name 
> is UTF-16? Blame Microsoft.

I know a lot of things to blame Microsoft for, but in the Unix world, all 
files are essentially sequences of bytes that you read or write, and it is 
your problem to know the semantic of these sequences. So this is not much 
better than in the Microsoft world.

In any case, Ada.Text_IO.Create is a good example.

As much as I understand you, if Name is of type Universal_String'Class and 
you call Ada.Text_IO.Create(File, Name) you expect the proper thing to 
happen, right?

I agree that this would be cool. But it just cannot work!

Right now, if the encoding of Name is, say, ISO-Latin-1 and the encoding 
the underlying filesystem expects is UTF-8, you can have really surprising 
results when calling Ada.Text_IO.Create(File, Name). It would be cool to 
solve this issue with some Universal_String type.

But firstly, the strings we have don't know their encoding. The 
application programmer knows (hopefully), but it is not part of String.

Secondly, even if we had some kind of enhanced string type with object 
Name storing its own encoding, in addition to the string itself, the 
library wouldn't know which encoding it to convert Name into, or if 
any conversion is needed at all!

The point is, you can mount different filesystems with different naming 
and encoding conventions, even on the same machine. (With Linux for 
sure, I guess that also works in the Microsoft world.)

No Universal_ type will solve this issue -- you just cannot get rid of 
explicit conversions. At the end of the day, something such as opening or 
creating a file is some kind of a low-level operation, alas.

>> I think, I agree with Randy here. The old bunch of strings are a mess,
>
> There is nothing wrong with them except for being not in the same class.
> [Literals could be done better]

> Furthermore what Randy proposes will actually be worse than pitiful
> Unbounded_String. For them you could at least do this:
>
>   type Relative_File_Path is new Unbounded_String;
>   type Absolute_File_Path is new Unbounded_String;
>
> You could not do that for tagged strings.

OK, here we agree. Whatever the "new" strings are, the ability to define 
incompatible types with the same representation, that you cannot mix 
(without explicit conversion) is important for a language supporting 
safety-critical stuff! I sometimes have types Tainted_String and 
Save_String, being both derived from [Wide_[Wide_]]String, and I am happy 
when the compiler stops me from messing up between variables of this type. 
Does Randy's proposal really not allow that?


------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-05 19:34                                                                                                                           ` Dmitry A. Kazakov
@ 2013-04-05 20:23                                                                                                                             ` Stefan.Lucks
  2013-04-06  7:39                                                                                                                               ` Dmitry A. Kazakov
  2013-04-05 20:38                                                                                                                             ` Stefan.Lucks
  1 sibling, 1 reply; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-05 20:23 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 2238 bytes --]

On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:

> On Fri, 5 Apr 2013 21:02:43 +0200, Stefan.Lucks@uni-weimar.de wrote:

> No, I insist that it is up to the programmer to decide whether two types to
> become compatible (relative) or not. Character and Wide_Character are
> evidently relative.

Integer and Float are "evidently relative".

> I disagree. They wanted to prevent the mess of PL/1 where *arbitrary*
> conversions were applied to semantically unrelated types. Types like
> Character and Wide_Character are semantically related. Conversion from one
> to another is perfectly well defined.

The same for conversions between Integer and Float.

>> Sure, some cases where implicit conversions take place
>> exist, but only very few. One example is the conversion of constants of
>> type Universal_Something into the right type.
>
> It makes sense in all cases where types are related. This is simply the
> definition of a type S being a subtype of T <=> S is substitutable for T.

And Integer is substitutable for Real.

> If representations are different the substitution is done per conversion.
> Not a rocket science, really.

Clearly, the designers of Ada where reluctant to define an implicit 
conversion from Integer to Float. I am glad about that -- it frequently 
helps me catching errors. Similarly for the distinction between different 
String types.

Sure, explicit conversions, are sometimes annoying, and so is the mess 
with constants. That is the same for string types as for arithmetic ones.

E.g. I frequently get caught by the compiler writing, say, "2" where I 
would have to write "2.0" for a constant Float.

> And it is all up to the programmer to tell the compiler that S must be
> considered a subtype of T, whatever representation both might have is not
> language's business.

Arithmetic types and String types are in the same boat here. There is no 
logical reason to allow implicit conversions for one class and not for the 
other one.


------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-05 19:34                                                                                                                           ` Dmitry A. Kazakov
  2013-04-05 20:23                                                                                                                             ` Stefan.Lucks
@ 2013-04-05 20:38                                                                                                                             ` Stefan.Lucks
  1 sibling, 0 replies; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-05 20:38 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 1573 bytes --]

On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:

> We are discussing deficiencies of Ada type system, unable to capture
> relations between domain specific entities modeled as objects and types.

Well, that is a broader discussion than the part I was in, that was about 
the need for some Universal_String type, but OK.

> E.g. few built-in numeric types, which are supposed to fit everything and
> expectedly fail, because predefined numbers have properties you might not
> need and miss ones you do need. The Op's subtype Prim was a perfect example
> of such a failure. Prime numbers are neither additive nor multiplicative.
> It is not a group. Yet Prime inherited the interface of a group from base
> type (Positive) and there is no way to prohibit this. It also inherited the
> order of Positives ('Succ), which is not one of Prime, and, again, there is
> no language means for fix that.

Here, I have agree with you.

I understand that for historical reasons Prime'Succ is actually 
Prime'Base'Succ, and the designers of Ada 2012 have unable to get rid of 
that without introducing too many incompatibilities.

But Prime'Succ(5)=4 is a big OUCH!

I hope that Ada 2020 (or whatever) will prohibit the attibutes Succ and 
Pred for all subtypes with dynamic predicates! (I think, First and Last 
are prohibited anyway.)



------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-05  9:57                                                                                                             ` Dmitry A. Kazakov
  2013-04-05 12:45                                                                                                               ` Stefan.Lucks
@ 2013-04-06  1:20                                                                                                               ` Randy Brukardt
  2013-04-06  5:20                                                                                                                 ` Usefulness of OOP (was Is this expected behavior or not) J-P. Rosen
  2013-04-07  7:00                                                                                                                 ` Is this expected behavior or not Dmitry A. Kazakov
  1 sibling, 2 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-04-06  1:20 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1bj564vat3q1j$.1s4d00rlzx4ux$.dlg@40tude.net...
> On Thu, 4 Apr 2013 15:31:23 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1fmcdkj58brky.bjedt0pr39cd$.dlg@40tude.net...
>>> On Wed, 3 Apr 2013 19:04:24 -0500, Randy Brukardt wrote:
>>>
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>>> news:1gkxiwepaxvtt$.u3ly33rbwthf.dlg@40tude.net...
>>>
>>>>> If you have more than one controlled argument/result of the same type,
>>>>> that makes it a multi-method. The natural consequence of this is that 
>>>>> all
>>>>> possible combinations of types from the hierarchy are specific bodies 
>>>>> to
>>>>> inherit/override. In Ada 95 only the bodies when all types are same 
>>>>> can
>>>>> be overridden. Statically the compiler prevents calls to mixed types 
>>>>> bodies,
>>>>> but they nevertheless exist and can be reached through dispatch. In 
>>>>> that
>>>>> case it works as if the body were "rase Constraint_Error." This hack
>>>>> won't work for &, =, <, <= etc. Those require almost all combinations 
>>>>> to work.
>>>>
>>>> I see where you are coming from, but I don't agree with any of it on a
>>>> fundamental level: mixing types in operations is virtually always an
>>>> error (either a real mistake or a design error).
>>>
>>> How is it an error to compare String and Wide_String?
>>
>> The same way it is an error to compare a float and an integer.
>
> It is not same. R and Z are different mathematical constructs. Unicode
> strings, all of them, are semantically exactly same except for encoding
> [representation] and constraints put on the code point set.

We're not talking about "Unicode strings", whatever that is. We're talking 
about an abstract string type, with different sets of characters, not 
necessarily overlapping. Automatically converting Wide_String into String is 
unsafe as it loses information, and that's even more true once you start 
thinking about other character sets.

I'm sure that there are cases where you can get away with automatic 
conversions, but you don't need that and you certainly can't do it all the 
time. So why support it at all?

>> You could
>> make a rule with somewhat sensible results, but it's a bad idea because 
>> it
>> hides more errors than it simplifies correct code.
>
> If that were so, you should not have them in the same hierarchy. You want
> to have one class in order to share operations like Put_Line. These
> operations are far more questionable than comparison. If you challenge
> comparison, you should not do Put_Line either.

To some extent, you are right. If you can't convert the value into some 
universal representation, then you can't implement class-wide operations, 
either.

And that suggests that the entire idea is bad. Indeed, that indicates that 
all OOP is bad because it destroys type-checking. Perhaps I should forget 
that I ever heard of it??

But in any case, there are two important differences here: single operand 
operations vs. multiiple operand operations, and the declaration (by using 
'Class) that you are explicitly not caring about type. Perhaps it is 
orthodoxy, but I don't believe that you should ever mix types without 
explicit conversions, meaning that only single operand operations can have 
'Class operands. (I can't think off hand of any cases where we ever had more 
than one operand of a class in a Claw operation, but I may have forgotten 
something.)

> You design decisions are motivated by compiler implementation issues not 
> by
> the actual properties of strings.

If you can't implement it, no mattter how wonderful some idea may be, it's 
still irrelevant.

...
> Now this:
>
>    function Get_Text (Control : Edit_Box) return Root_String_Type;

First, this is illegal because Root_String_Type is abstract, and you can't 
have a function returning an abstract type.

Second, you can't implement that in Claw (or Ada), because the Edit_Box is 
an "in" parameter and you need to modify some of its components in order to 
deal with the state changes of the edit box.

So you have have to have something like:

    function Get_Text (Control : in out Edit_Box) return 
Root_String_Type'Class;

But this is very different than the procedure form. In the procedure case, 
the object passed in determines the type and representation of the result. 
In the function case, the function returns whatever type it feels like, and 
just about the only thing you can do with it is assign it to an object or 
pass it to a class-wide parameter. So this is trivial to implement: return 
any old new object that you like.

Probably here again you want to totally redesign Ada, but that isn't very 
likely.

>>>>> The only pattern that sometimes works is recursive cascaded dispatch.
>>>>> That is when you make one argument controlled and another class-wide.
>>>>
>>>> Gosh, that's what I was talking from the beginning.
>>>
>>> It works only with dyadic operations, procedures or else functions
>>> returning an alien type.
>>
>> Which is 95% of the cases that you would want.
>
> No more than 20-30% actually.

OK, it's 95% of the cases that occur in actual practice, with the possible 
exception with people that overuse OOP constructs and make their systems 
more complex than needed. :-)

...
>> Mixed operations are almost always a non-starter for any type.
>
> Mixed operations are a must for all algebraic types and all string types.
> Ada 83 had it mixed from the start, e.g. Universal_Integer vs. Integer. 
> Ada
> 95 added mixed operations for access types.

Actually, those aren't really mixed, as Universal has the same relationship 
to other types as 'Class does. In some ways, these act as separate types, 
but given the automatic conversions they really aren't that - they're a set 
of types that includes the associated specific types.

...
>> the Ada 95 effects make it absolutely
>> necessary to avoid functions returning a controlled type, else creating
>> extensions is so hard that no one will do it.
>
> I don't know where you get that idea. I never had any problem with 
> abstract
> factories.

Well, I have. As I previously explained, the abstract routines and functions 
in the Claw Builder root types make it so time-consuming to create an 
extension (the last one I did took around 20 hours to write, and even then I 
never finished it) that it's impractical to do so.

If you have only one such routine, there is no significant problem, but you 
have to greatly limit the number or extensions are impractical. The only 
practical extensions inherit virtually all of their implementation (at least 
initially) from their parent. [This is how Claw itself works, it's a lot 
easy to deal with than the builder is.] It's a major reason why I don't 
believe in interfaces, as the effort to create implementations for every 
included operation is just too much of a "Big Bang" for my programming 
style. (If I can't have something compilable and testable in a few hours, I 
get very uncomfortable, because that is the only way to detect gross 
mistakes -- otherwise, one can waste days building something that doesn't 
work.)

> Actual problem is fighting senseless limitations imposed by the
> language, which makes design very hard as you never know if the derived
> type would be possible to construct. Limited aggregates/functions, broken
> initialization/finalization, leaking separation of specification and
> implementation, missing initialization/finalization of class-wides etc.
> That makes it difficult.

Not sure why most of those things would cause any real issues, as most of 
them give more, not less, capability. But it isn't worth discussing that.

>>> Not at all, the compiler is free to choose, so it must. [I don't 
>>> consider
>>> schizophrenic compilers choosing one way and doing in another. That does
>>> not work with any model.]
>>
>> It doesn't work for portability reasons for some compilers to call Adjust
>> during the evaluation of parameters and other compilers to not call 
>> Adjust.
>
> When the type neither specified as either by-reference nor as by-value, it
> shall be exactly this way. I don't understand why this is relevant.
>
>> It would make performance wildly variable and possibly cause bugs (if the
>> program unintentionally depended on one or the other.
>
> Yes, the language permits compilers implemented poorly, and?

This has nothing to do with compilers. It has to do with *poorly designed 
programs*. It's certainly true that a program that depends on by-copy or 
by-reference passing is wrong; the compiler should be free to choose. But 
this is an undetectable error. And bringing Adjust into it makes it much 
worse, because it's easy to write code that doesn't work if Adjust is called 
(you probably can get infinite recursion that way). That sort of thing can't 
be implementation-defined.

...
>>>> It strikes me that the model of stripping tags means that type 
>>>> conversion
>>>> of an object to a class-wide type would effectively change the tag (if 
>>>> the
>>>> routine was inherited or called by a conversion of an operand).
>>>
>>> Yes, re-dispatch is a broken thing. Don't do it, because it is ambiguous
>>> in general case when objects do not have an identity. By-copy scalar 
>>> types
>>> are such things. There is nothing which could distinguish Integer 13 
>>> from
>>> Long_Integer 13 except the context. Once you dispatched that information
>>> is lost. There is no way back.

Here you are saying that you can't redispatch because you insist on a model 
that doesn't allow it. I don't think that is a very good case. :-) You have 
to justify eliminating re-dispatch, then, and only then, can you chose a 
model that doesn't allow it.

>>>> That would
>>>> mean that the behavior of such a conversion would be very different for
>>>> an untagged type and for a tagged type.
>>>
>>> Not different. It is just so that tagged types per design have type
>>> identity. Other types simply don't have it.
>>
>> Objects of limited types are always assumed to have an identity;
>
> No. E.g. task and protected types lack type identity. Only tagged types
> have type identity.
>
> Note that type identity /= object identity (e.g. machine address where the
> object resides).

I don't think that they ought to be separated. If you have object identity, 
and every object has a nominal type, it does not make sense to lose that 
information. There are no values of a limited type, only objects. I see your 
point for non-limited values, as the type of a value is not necessarily 
determined. But that's not true for objects.

Here again, you are justifying your model by simply eliminating a property 
that all objects have and saying that I can't fit that into my model so I 
won't.

 >>>> A more general model that is many times more complex than the existing
>>>> model. What exactly is being simplified?
>>>
>>> You will have all strings in one hierarchy. All characters in another. 
>>> All
>>> integer types in third. Tagged types described using a footnote.
>>
>> That's already true, you just don't have inheritance of operations for 
>> these
>> hierarchies. So exactly what you are simplifying but introducing this 
>> whole
>> new notion of type cloning, this new notion of when you must override
>> routines, and so on??
>
> I don't introduce anything Ada 83 or 95 do not have already. I want to 
> lift
> meaningless language limitations which lead to silly design decisions like
> inability to concatenate or compare two strings.

That's a feature, not a bug. :-) And it's one I would be extremely surprised 
to see changed in Ada (or any other strongly typed language, for that 
matter).

>>> You want to derive each string type straight from Root_String.
>>
>> Yes, or from related ones. There is no significant value to doing 
>> anything
>> else - as you point out, if you can inherit the operations, the
>> representations have to be compatible. So there is nothing useful you can 
>> do
>> with multiple levels.
>
> Encoding!

You have to reimplement *every* operation for a new representation (in your 
model as well as in existing Ada). So you are gaining absolutely nothing 
over using interfaces for any added operations.

You need to have a more complete example than that if you want to convince 
me of anything.

                                          Randy.


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

* Re: Is this expected behavior or not
  2013-04-05 16:29                                                                                                                     ` Dmitry A. Kazakov
  2013-04-05 19:55                                                                                                                       ` Stefan.Lucks
@ 2013-04-06  1:38                                                                                                                       ` Randy Brukardt
  1 sibling, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-04-06  1:38 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:pgrgoxdhtshv$.z253qtbqarkc.dlg@40tude.net...
> On Fri, 5 Apr 2013 17:16:59 +0200, Stefan.Lucks@uni-weimar.de wrote:
...
> I disagree. They wanted to prevent the mess of PL/1 where *arbitrary*
> conversions were applied to semantically unrelated types. Types like
> Character and Wide_Character are semantically related. Conversion from one
> to another is perfectly well defined.

All numeric types are semantically related. All array types are semantically 
related. But that doesn't mean that implicit conversions are a good idea 
even if they are well-defined.

Every type that has a different representation has different semantics, and 
those differences are important in enough cases that implicit conversion 
between different representations is banned.

This *is* an accurate description of Ada's design: you can't derive a 
numeric type that has primitive operations if you try to change its 
representation, and that's because the implicit conversions of inheritance 
were not to be allowed if the representation is different. (This is one of 
the things that makes Ada 83 derivation so utterly useless.)

> Furthermore what Randy proposes will actually be worse than pitiful
> Unbounded_String. For them you could at least do this:
>
>   type Relative_File_Path is new Unbounded_String;
>   type Absolute_File_Path is new Unbounded_String;
>
> You could not do that for tagged strings.

Right. You'd have to write:

   type Relative_File_Path is new Unbounded_String is null record;
   type Absolute_File_Path is new Unbounded_String is null record;

Horrifyingly more complex. ;-)

                                         Randy.



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

* Re: Is this expected behavior or not
  2013-04-05 19:55                                                                                                                       ` Stefan.Lucks
@ 2013-04-06  1:45                                                                                                                         ` Randy Brukardt
  2013-04-06  7:54                                                                                                                         ` Dmitry A. Kazakov
  1 sibling, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-04-06  1:45 UTC (permalink / raw)


<Stefan.Lucks@uni-weimar.de> wrote in message 
news:alpine.DEB.2.02.1304052103590.31746@debian...
...
>OK, here we agree. Whatever the "new" strings are, the ability to define
>incompatible types with the same representation, that you cannot mix
>(without explicit conversion) is important for a language supporting
>safety-critical stuff! I sometimes have types Tainted_String and
>Save_String, being both derived from [Wide_[Wide_]]String, and I am happy
>when the compiler stops me from messing up between variables of this type.
>Does Randy's proposal really not allow that?

Of course they're different types. They wouldn't be mixable amongst 
themselves (Dmitry's obcession with multi-methods would of course erode any 
such protections).

They both would implicitly convert to Root_String'Class, of course, and 
there wouldn't be any way to prevent that. But I can't see any particular 
new problem with this, you have the same effect for any Ada tagged type and 
associated class-wide type.

I know Dmitry would like to have some sort of way to split off clones of 
types that are completely incompatible, but that would have severe 
consequences with the other uses for type hierarchies (conversions and 
formal types), as those could not be allowed either.

                                                  Randy.


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

* Usefulness of OOP (was Is this expected behavior or not)
  2013-04-06  1:20                                                                                                               ` Randy Brukardt
@ 2013-04-06  5:20                                                                                                                 ` J-P. Rosen
  2013-04-06 10:31                                                                                                                   ` Dmitry A. Kazakov
  2013-04-07  7:00                                                                                                                 ` Is this expected behavior or not Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-04-06  5:20 UTC (permalink / raw)


Le 06/04/2013 03:20, Randy Brukardt a écrit :
> And that suggests that the entire idea is bad. Indeed, that indicates that 
> all OOP is bad because it destroys type-checking. Perhaps I should forget 
> that I ever heard of it??

Can't resist jumping on this one...

Yes, OOP increases dynamicity, which is good in some contexts, at the
cost of decreasing strong typing and static checkability.

Drawbacks and benefits, you have to decide depending on context. Nothing
new with that... Just mentionned it to counter those who claim that OOP
is the universal cure, and that other methods (like good ol' structured
programming) are just remainings of the past.
-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


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

* Re: Is this expected behavior or not
  2013-04-05 20:23                                                                                                                             ` Stefan.Lucks
@ 2013-04-06  7:39                                                                                                                               ` Dmitry A. Kazakov
  2013-04-07 18:10                                                                                                                                 ` Stefan.Lucks
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-06  7:39 UTC (permalink / raw)


On Fri, 5 Apr 2013 22:23:13 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:
> 
>> On Fri, 5 Apr 2013 21:02:43 +0200, Stefan.Lucks@uni-weimar.de wrote:
> 
>> No, I insist that it is up to the programmer to decide whether two types to
>> become compatible (relative) or not. Character and Wide_Character are
>> evidently relative.
> 
> Integer and Float are "evidently relative".

No, as I said it is in the application domain. If your domain were
mathematical analysis then, yes, integer and float would be related. When
the domain is engineering they are clearly not, because in that domain as
well as in most other domains, number is used not as number, but as an
object modeling something else.

>> I disagree. They wanted to prevent the mess of PL/1 where *arbitrary*
>> conversions were applied to semantically unrelated types. Types like
>> Character and Wide_Character are semantically related. Conversion from one
>> to another is perfectly well defined.
> 
> The same for conversions between Integer and Float.

Nope. You cannot convert house number to outdoor temperature.

>> And it is all up to the programmer to tell the compiler that S must be
>> considered a subtype of T, whatever representation both might have is not
>> language's business.
> 
> Arithmetic types and String types are in the same boat here.

String types are not models when we consider major use cases for
String/Wide_String/Wide_Wide_String. They are entities from one domain
meaning same entities [domain: Unicode].

Certainly there are cases when strings can be used to model something else.
But it is highly unlikely that they would distinguish String and
Wide_String either.

Numbers are clearly different, e.g. counting apples and oranges [domain:
grocery]

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

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

* Re: Is this expected behavior or not
  2013-04-05 19:55                                                                                                                       ` Stefan.Lucks
  2013-04-06  1:45                                                                                                                         ` Randy Brukardt
@ 2013-04-06  7:54                                                                                                                         ` Dmitry A. Kazakov
  2013-04-07 18:17                                                                                                                           ` Stefan.Lucks
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-06  7:54 UTC (permalink / raw)


On Fri, 5 Apr 2013 21:55:27 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Fri, 5 Apr 2013, Dmitry A. Kazakov wrote:
> 
>> On Fri, 5 Apr 2013 17:16:59 +0200, Stefan.Lucks@uni-weimar.de wrote:
> 
>>> I agree with you that there is no reason to distinguish between them. The
>>> entire distinction narrow, Wide_ and Wide_Wide_ Strings (and Characters)
>>> is a historical artifact, no more, no less.
>>>
>>> But if there is no reason to disting between them -- there is no reason to
>>> mix them either!
>>
>> Sorry, but it cannot be both.
> 
> No, if you mix them, you must distinguish them. At least, when 
> implementing your own multi-method, such as
> 
>    function Longest_Common_Substring(S1, S2: Universal_String)
>                                     return Universal_String;
>                                               -- maybe "is abstract";
> 
> Either Universal_String is abstract, then so would be this multi-method, 
> and you would to override it n^3 times, when supporting n different string 
> types.

You could inherit it per composition with conversion [the language should
support this sort of delegation].

> Or you can actually have objects of type Universal_String, but then 
> using this method without making explicit conversions means a whole new 
> bunch of implicit conversions.

Actually there are more than 2 alternatives. Either argument and/or result
can covariant or contravariant.

> One problem with implicit conversions is that Strings don't "know" their 
> encoding (Is it UTF-8? Or ISO-Latin-1? Or ...?), so you don't even have 
> the information you need to perform the conversion.

The space of related types is at least 3D:

1. One hierarchy follows the hierarchy of characters: Wide_Wide_Character
:> Wide_Character :> Character :> ASCII_Character + EBCDIC_Character etc.

2. Another hierarchy is about constrained vs. unbounded strings

3. The third hierarchy encompasses encoding.

For each two points in this space it is perfectly clear how to convert one
to another.

> Which is why you need to make explicit conversions.

There is no need in explicit conversions because it is well defined how to
obtain one string from another.

> And then it is not a big leap to say "convert everything into my favourite 
> kind of string, then call my method, and then convert the result back".

This one possible implementation. Once you have a mesh of related types you
can define specific bodies for interesting combinations of arguments and
leave other generated per composition with conversion.

>> Consider Ada.Text_IO.Create. It has name a string and content. You tell 
>> us that it is not necessary to be able to open an UTF-8 file which name 
>> is UTF-16? Blame Microsoft.
> 
> I know a lot of things to blame Microsoft for, but in the Unix world, all 
> files are essentially sequences of bytes that you read or write, and it is 
> your problem to know the semantic of these sequences.

Which is why you need a Text_IO package for each combination content
encoding x name encoding.

> In any case, Ada.Text_IO.Create is a good example.
> 
> As much as I understand you, if Name is of type Universal_String'Class and 
> you call Ada.Text_IO.Create(File, Name) you expect the proper thing to 
> happen, right?

I meant two arguments:

   Name => some string type
   Form => some encoding of the content

as an example when different string types must be mixed. Under MS Windows
so called W-calls use UTF-16 encoded names, while the file content could be
anything, e.g. UTF-8. You can guess how many combinations exist.

> But firstly, the strings we have don't know their encoding.

They know. See 3.5.2 which defines character set.

Yes, some people including me use String for UTF-8 and Wide_String for
UTF-16. This is clearly wrong. UTF-8 string is equivalent to
Wide_Wide_String and cannot be reinterpreted as String. 

> No Universal_ type will solve this issue -- you just cannot get rid of 
> explicit conversions.

You can. Actually, what people do right now is implicit unchecked
conversions from UTF-8 to String. It is even worse than PL/1, it is plain
wrong, C-esque of worst kind. Unfortunately Ada simply offers no means to
design it right.

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


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

* Re: Usefulness of OOP (was Is this expected behavior or not)
  2013-04-06  5:20                                                                                                                 ` Usefulness of OOP (was Is this expected behavior or not) J-P. Rosen
@ 2013-04-06 10:31                                                                                                                   ` Dmitry A. Kazakov
  2013-04-06 18:43                                                                                                                     ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-06 10:31 UTC (permalink / raw)


On Sat, 06 Apr 2013 07:20:39 +0200, J-P. Rosen wrote:

> Just mentionned it to counter those who claim that OOP
> is the universal cure, and that other methods (like good ol' structured
> programming) are just remainings of the past.

Actually both OOA/D and structured programming remain deep in the past as
they share the same principle of designing rather an individual system,
which leads to extremely fragile design. Traditional OOA/D considers the
system composed out of objects collaborating with each other. This is quite
similar to modules of structured approach. The difference is in object
orientation against more loose [almost ad-hoc] procedural decomposition of
classic structured programming.

Both greatly hinder re-use and fail to adapt to the reality of ever
changing requirements. [*]

What is good in OO is more advanced ADT, which supports decomposition in
more general, and thus more stable, terms, e.g. along types and sets of
types (AKA generic programming). It in turn requires more advanced system
of modules to hold ADTs, e.g. Ada's system of packages.

Comparing to decomposition along types and sets of types, traditional OOA/D
and structured programming decompose software along individual
objects/values/routines. Paleolith.

P.S. I don't consider type safety issue because structured programming did
not operate types. It was basically pre-typed = untyped.

----------------------------
* There is a whole "OO religion" teaching that the world indeed consists
out of objects which program design could capture. This in turn would
ensure stability of the design. Utter nonsense, for sure.

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


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

* Re: Usefulness of OOP (was Is this expected behavior or not)
  2013-04-06 10:31                                                                                                                   ` Dmitry A. Kazakov
@ 2013-04-06 18:43                                                                                                                     ` Georg Bauhaus
  0 siblings, 0 replies; 242+ messages in thread
From: Georg Bauhaus @ 2013-04-06 18:43 UTC (permalink / raw)


On 06.04.13 12:31, Dmitry A. Kazakov wrote:
> Both [procedural decomposition and OO] greatly hinder re-use and
>  fail to adapt to the reality of ever changing requirements.


Requirements do change. Change is always managed in some way. What if
we knew well how methods and languages influence the cost and outcome
of change management? I mean formally, more scientifically. We do know
about time spent on adapting software to changing requirements. This
means we know the cost. But do we know why this or that change has
cost more or less? I mean, formally, so that some theory could lead
the way to better methods, and to better languages.

A science of successful reactions to change, in terms of methods of
programming, would seem to be a bigger project for academics
co-operating with industry. Is it on anyone's radar? I speculate that
proprietary building blocks for software are moving ahead, without
feedback arriving in language design.  (I hope I am wrong.)

A possible idea that I admit is foggy: Is there something in GoF
patterns worth of making them new primitives of formal expression?



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

* Re: Is this expected behavior or not
  2013-04-06  1:20                                                                                                               ` Randy Brukardt
  2013-04-06  5:20                                                                                                                 ` Usefulness of OOP (was Is this expected behavior or not) J-P. Rosen
@ 2013-04-07  7:00                                                                                                                 ` Dmitry A. Kazakov
  2013-04-09 23:24                                                                                                                   ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-07  7:00 UTC (permalink / raw)


On Fri, 5 Apr 2013 20:20:58 -0500, Randy Brukardt wrote:

> Automatically converting Wide_String into String is 
> unsafe as it loses information, and that's even more true once you start 
> thinking about other character sets.

All existing character sets are subsets of Unicode. String could be an Ada
subtype of Wide_String. Only difference is in the representation.

Even more this applies to encoding. Clearly encoding has nothing to do with
the content of a string.

> And that suggests that the entire idea is bad. Indeed, that indicates that 
> all OOP is bad because it destroys type-checking. Perhaps I should forget 
> that I ever heard of it??

You conflate type checking with representation checking. There is no need
to check how a string is represented.
 
> But in any case, there are two important differences here: single operand 
> operations vs. multiiple operand operations,

This difference is only important because the type model you deploy cannot
handle the later. There should be something wrong with the model then.

>> Now this:
>>
>>    function Get_Text (Control : Edit_Box) return Root_String_Type;
> 
> First, this is illegal because Root_String_Type is abstract, and you can't 
> have a function returning an abstract type.
> 
> Second, you can't implement that in Claw (or Ada), because the Edit_Box is 
> an "in" parameter and you need to modify some of its components in order to 
> deal with the state changes of the edit box.
> 
> So you have have to have something like:
> 
>     function Get_Text (Control : in out Edit_Box) return 
> Root_String_Type'Class;

You will need explicit conversions wherever you use Get_Text:

      X : UTF8_String := Box.Get_Text;

or

      Open (Box.Get_Text);
 
>>>>>> The only pattern that sometimes works is recursive cascaded dispatch.
>>>>>> That is when you make one argument controlled and another class-wide.
>>>>>
>>>>> Gosh, that's what I was talking from the beginning.
>>>>
>>>> It works only with dyadic operations, procedures or else functions
>>>> returning an alien type.
>>>
>>> Which is 95% of the cases that you would want.
>>
>> No more than 20-30% actually.
> 
> OK, it's 95% of the cases that occur in actual practice,

They don't occur in practice because the language simply does not support
it.

As for cascaded dispatch, it is incredibly error prone. Note that cascaded
dispatch involves complementary operations, e.g. let you dispatch on T1<T2:

   function "<" (Left : T; Right : T'Class) return Boolean;

If T2 is a descendant of T1, you have to re-dispatch on T2 within the body
of "<". But that would invert the order of arguments! This is another
operation (complementary) you must go after:

   not (T2 >= T1)

Yet another issue is preventing recursion of cascaded dispatch. You need a
whole set of internal operations with additional parameters to keep track
of re-dispatching calls.

It is exceptionally difficult to implement already in such simple case as
<. 

>>> the Ada 95 effects make it absolutely
>>> necessary to avoid functions returning a controlled type, else creating
>>> extensions is so hard that no one will do it.
>>
>> I don't know where you get that idea. I never had any problem with 
>> abstract factories.
> 
> Well, I have. As I previously explained, the abstract routines and functions 
> in the Claw Builder root types make it so time-consuming to create an 
> extension (the last one I did took around 20 hours to write, and even then I 
> never finished it) that it's impractical to do so.
> 
> If you have only one such routine,

Why there should be many?

Anyway, if you know how to create such function, you make it class-wide. If
you don't know, nobody knows. It must be overridden and the compiler tells
you so. There is simply no problem with that.

>>>> Not at all, the compiler is free to choose, so it must. [I don't consider
>>>> schizophrenic compilers choosing one way and doing in another. That does
>>>> not work with any model.]
>>>
>>> It doesn't work for portability reasons for some compilers to call Adjust
>>> during the evaluation of parameters and other compilers to not call 
>>> Adjust.
>>
>> When the type neither specified as either by-reference nor as by-value, it
>> shall be exactly this way. I don't understand why this is relevant.
>>
>>> It would make performance wildly variable and possibly cause bugs (if the
>>> program unintentionally depended on one or the other.
>>
>> Yes, the language permits compilers implemented poorly, and?
> 
> This has nothing to do with compilers. It has to do with *poorly designed 
> programs*. It's certainly true that a program that depends on by-copy or 
> by-reference passing is wrong; the compiler should be free to choose. But 
> this is an undetectable error. And bringing Adjust into it makes it much 
> worse, because it's easy to write code that doesn't work if Adjust is called 
> (you probably can get infinite recursion that way).

Are you saying the copy constructors (Adjust) are broken in Ada? They are
to me too. Fix them.

>>>>> It strikes me that the model of stripping tags means that type conversion
>>>>> of an object to a class-wide type would effectively change the tag (if the
>>>>> routine was inherited or called by a conversion of an operand).
>>>>
>>>> Yes, re-dispatch is a broken thing. Don't do it, because it is ambiguous
>>>> in general case when objects do not have an identity. By-copy scalar types
>>>> are such things. There is nothing which could distinguish Integer 13 from
>>>> Long_Integer 13 except the context. Once you dispatched that information
>>>> is lost. There is no way back.
> 
> Here you are saying that you can't redispatch because you insist on a model 
> that doesn't allow it.

No model exist which would allow re-dispatch on scalar value. Like no model
exist where 2+2=5.

>>>>> That would
>>>>> mean that the behavior of such a conversion would be very different for
>>>>> an untagged type and for a tagged type.
>>>>
>>>> Not different. It is just so that tagged types per design have type
>>>> identity. Other types simply don't have it.
>>>
>>> Objects of limited types are always assumed to have an identity;
>>
>> No. E.g. task and protected types lack type identity. Only tagged types
>> have type identity.
>>
>> Note that type identity /= object identity (e.g. machine address where the
>> object resides).
> 
> I don't think that they ought to be separated. If you have object identity, 
> and every object has a nominal type, it does not make sense to lose that 
> information.

Nothing is lost. You forgot that the parameter was passed by copy, as
required by the type, which was by-copy. It is another object in there. Its
identity is obviously not the identity of the origin. How could it be
otherwise?

>>>> You want to derive each string type straight from Root_String.
>>>
>>> Yes, or from related ones. There is no significant value to doing anything
>>> else - as you point out, if you can inherit the operations, the
>>> representations have to be compatible. So there is nothing useful you can 
>>> do with multiple levels.
>>
>> Encoding!
> 
> You have to reimplement *every* operation for a new representation (in your 
> model as well as in existing Ada).

Most bodies will be inherited per composition with conversion.

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

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

* Re: Is this expected behavior or not
  2013-04-06  7:39                                                                                                                               ` Dmitry A. Kazakov
@ 2013-04-07 18:10                                                                                                                                 ` Stefan.Lucks
  2013-04-07 18:23                                                                                                                                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-07 18:10 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 1650 bytes --]

On Sat, 6 Apr 2013, Dmitry A. Kazakov wrote:

>> The same for conversions between Integer and Float.
>
> Nope. You cannot convert house number to outdoor temperature.

So what? Neither can I convert my zip code to my birth year (both 
Positive) or the outdoor temperature to speed of light. ;-)

Ada allows to define types such as, Apples and Oranges, or, say Speed and 
Temperature. But this has nothing to do with the underlying mathematical 
struture of each of these types.

Actually, mixing integers and float (or integers and fixed-point numbers) 
is not that uncommon. The maximum speed for a vehicle, say, a train at a 
certain part of the track, is, most likely, an integer, while the speed 
the sensors measure isn't an integer. So you have something like the 
following code:

   Current_Speed : Speed;
   Max_Speed     : Integer_Speed;
   Safety_Margin : constant Speed := ...
   ...
   if Current_Speed > Speed(Max_Speed) then
     Display_Warning(Speed_Warning);
     Play_Alarm_Sound;
     if Current_Speed < (Speed(Max_Speed) + Safety_Margin) then
       Perform_Emergency_Break;
     end_if:
   end_if;

Here, you need the to convert Max_Speed to Speed, even though the two 
types Speed and Integer_Speed have the same semantic.

I don't think we'll agree on this issue, but I fail to see any significant 
distinction between the class of arithmetic types and string types.



------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-06  7:54                                                                                                                         ` Dmitry A. Kazakov
@ 2013-04-07 18:17                                                                                                                           ` Stefan.Lucks
  2013-04-07 18:28                                                                                                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-07 18:17 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 1121 bytes --]

On Sat, 6 Apr 2013, Dmitry A. Kazakov wrote:

> On Fri, 5 Apr 2013 21:55:27 +0200, Stefan.Lucks@uni-weimar.de wrote:

>> In any case, Ada.Text_IO.Create is a good example.
[...]
>> No Universal_ type will solve this issue -- you just cannot get rid of
>> explicit conversions.
>
> You can. Actually, what people do right now is implicit unchecked
> conversions from UTF-8 to String. It is even worse than PL/1, it is plain
> wrong, C-esque of worst kind. Unfortunately Ada simply offers no means to
> design it right.

If you have mounted different filesystems using different encodings on 
your system, how on earth should Ada.Text_IO even "know" which encoding to 
apply? (And even if not, how would Ada.Text_IO "know" the proper 
encoding?)

Yes, this is C-esque of the worst kine. However, what would you expect 
when making system calls with operation systems written in C?

------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--

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

* Re: Is this expected behavior or not
  2013-04-07 18:10                                                                                                                                 ` Stefan.Lucks
@ 2013-04-07 18:23                                                                                                                                   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-07 18:23 UTC (permalink / raw)


On Sun, 7 Apr 2013 20:10:09 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Sat, 6 Apr 2013, Dmitry A. Kazakov wrote:
> 
>>> The same for conversions between Integer and Float.
>>
>> Nope. You cannot convert house number to outdoor temperature.
> 
> So what? Neither can I convert my zip code to my birth year (both 
> Positive) or the outdoor temperature to speed of light. ;-)

Which is the whole point.

> I don't think we'll agree on this issue, but I fail to see any significant 
> distinction between the class of arithmetic types and string types.

The distinction is one domain vs. many.

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

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

* Re: Is this expected behavior or not
  2013-04-07 18:17                                                                                                                           ` Stefan.Lucks
@ 2013-04-07 18:28                                                                                                                             ` Dmitry A. Kazakov
  2013-04-08  7:48                                                                                                                               ` Stefan.Lucks
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-07 18:28 UTC (permalink / raw)


On Sun, 7 Apr 2013 20:17:43 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Sat, 6 Apr 2013, Dmitry A. Kazakov wrote:
> 
>> On Fri, 5 Apr 2013 21:55:27 +0200, Stefan.Lucks@uni-weimar.de wrote:
> 
>>> In any case, Ada.Text_IO.Create is a good example.
> [...]
>>> No Universal_ type will solve this issue -- you just cannot get rid of
>>> explicit conversions.
>>
>> You can. Actually, what people do right now is implicit unchecked
>> conversions from UTF-8 to String. It is even worse than PL/1, it is plain
>> wrong, C-esque of worst kind. Unfortunately Ada simply offers no means to
>> design it right.
> 
> If you have mounted different filesystems using different encodings on 
> your system, how on earth should Ada.Text_IO even "know" which encoding to 
> apply?

How is this relevant to the issue that encoding must a part of the type?

> Yes, this is C-esque of the worst kine. However, what would you expect 
> when making system calls with operation systems written in C?

I expect the type system to handle equivalent types of different
representations such as UTF-8 and UCS-4 strings. As it already does in the
case Universal_Integer vs. Integer. Both are distinct types, both have
different representations, both are considered equivalent in certain cases.

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


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

* Re: Is this expected behavior or not
  2013-04-07 18:28                                                                                                                             ` Dmitry A. Kazakov
@ 2013-04-08  7:48                                                                                                                               ` Stefan.Lucks
  2013-04-08  8:59                                                                                                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-08  7:48 UTC (permalink / raw)


On Sun, 7 Apr 2013, Dmitry A. Kazakov wrote:

>> If you have mounted different filesystems using different encodings on
>> your system, how on earth should Ada.Text_IO even "know" which encoding to
>> apply?
>
> How is this relevant to the issue that encoding must a part of the type?

Because even if the implementation of Ada.Text_IO.Open would know the 
encoding of the filename, it could do nothing useful with it.

>> Yes, this is C-esque of the worst kine. However, what would you expect
>> when making system calls with operation systems written in C?
>
> I expect the type system to handle equivalent types of different
> representations such as UTF-8 and UCS-4 strings. As it already does in the
> case Universal_Integer vs. Integer. Both are distinct types, both have
> different representations, both are considered equivalent in certain cases.

Universal_Integer is a pseudo-type. You cannot define an object O: 
Universal_Integer, neither a function returning Universal_Integer ...

The only thing that Universal_Integer handles well is a neat way of 
defining constants. The mess with the different string types in Ada is not 
just about string constants, it goes much beyond.


------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--



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

* Re: Is this expected behavior or not
  2013-04-08  7:48                                                                                                                               ` Stefan.Lucks
@ 2013-04-08  8:59                                                                                                                                 ` Dmitry A. Kazakov
  2013-04-08 15:35                                                                                                                                   ` Stefan.Lucks
  2013-04-09 22:45                                                                                                                                   ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-08  8:59 UTC (permalink / raw)


On Mon, 8 Apr 2013 09:48:07 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Sun, 7 Apr 2013, Dmitry A. Kazakov wrote:
> 
>>> If you have mounted different filesystems using different encodings on
>>> your system, how on earth should Ada.Text_IO even "know" which encoding to
>>> apply?
>>
>> How is this relevant to the issue that encoding must a part of the type?
> 
> Because even if the implementation of Ada.Text_IO.Open would know the 
> encoding of the filename, it could do nothing useful with it.

??? It must know the encoding in order to handle the file properly.

>>> Yes, this is C-esque of the worst kine. However, what would you expect
>>> when making system calls with operation systems written in C?
>>
>> I expect the type system to handle equivalent types of different
>> representations such as UTF-8 and UCS-4 strings. As it already does in the
>> case Universal_Integer vs. Integer. Both are distinct types, both have
>> different representations, both are considered equivalent in certain cases.
> 
> Universal_Integer is a pseudo-type.

With pseudo-values and pseudo-operations used by pseudo-programmers? (:-))

> You cannot define an object O: 
> Universal_Integer, neither a function returning Universal_Integer ...

As if it were relevant. But you are wrong here. Universal types leak into
run time through attributes. I.e. you do have objects of universal types at
run time in expressions like

   Integer'Pos (X) * 2
 
> The only thing that Universal_Integer handles well is a neat way of 
> defining constants.

That is the whole point. It is already here, because it is needed.

> The mess with the different string types in Ada is not 
> just about string constants, it goes much beyond.

That is the reason why it should be fixed.

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



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

* Re: Is this expected behavior or not
  2013-04-08  8:59                                                                                                                                 ` Dmitry A. Kazakov
@ 2013-04-08 15:35                                                                                                                                   ` Stefan.Lucks
  2013-04-08 19:08                                                                                                                                     ` Dmitry A. Kazakov
  2013-04-09 22:53                                                                                                                                     ` Is this expected behavior or not Randy Brukardt
  2013-04-09 22:45                                                                                                                                   ` Randy Brukardt
  1 sibling, 2 replies; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-08 15:35 UTC (permalink / raw)


On Mon, 8 Apr 2013, Dmitry A. Kazakov wrote:

>> Because even if the implementation of Ada.Text_IO.Open would know the
>> encoding of the filename, it could do nothing useful with it.
>
> ??? It must know the encoding in order to handle the file properly.

Ah! Finally you seem to understand where the problem is!

Ada.Text_IO would have to know the encoding, but it doesn't. So it just 
treats the string like a sequence of bytes (much like a C-string) and 
leaves it to the Application Programmer to apply the proper conversion 
before. Which means, the conversion must be done explicitly.

>> Universal_Integer is a pseudo-type.
>
> With pseudo-values and pseudo-operations used by pseudo-programmers? (:-))

All objects of that type are constant. All operations are evaluated at 
compile time. Whenever values of this type make it into run-time objects, 
they magically change their type.

>> You cannot define an object O:
>> Universal_Integer, neither a function returning Universal_Integer ...
>
> As if it were relevant. But you are wrong here.

How so?

> Universal types leak into
> run time through attributes. I.e. you do have objects of universal types at
> run time in expressions like
>
>   Integer'Pos (X) * 2

You just used the already existing object 2 of type constant 
Universal_Integer. Even if you ignore the "constant", there is no 
*definition* (or *declaration*) of an object O: Universal_Integer.

>> The only thing that Universal_Integer handles well is a neat way of
>> defining constants.
>
> That is the whole point. It is already here, because it is needed.

I see. Some pseudo-type Universal_String might possibly help with string 
constants (I am not sure -- it is much more difficult to figure out the 
proper transformation to whatever string type you really need).

But the mess with string types in Ada goes deeper, and Universal_Strings 
would at best solve half of the problem.

YMMV, but I'd say much less than half of the problem.



------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--



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

* Re: Is this expected behavior or not
  2013-04-08 15:35                                                                                                                                   ` Stefan.Lucks
@ 2013-04-08 19:08                                                                                                                                     ` Dmitry A. Kazakov
  2013-04-09  7:18                                                                                                                                       ` Stefan.Lucks
  2013-04-09 22:53                                                                                                                                     ` Is this expected behavior or not Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-08 19:08 UTC (permalink / raw)


On Mon, 8 Apr 2013 17:35:17 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Mon, 8 Apr 2013, Dmitry A. Kazakov wrote:
> 
>>> Because even if the implementation of Ada.Text_IO.Open would know the
>>> encoding of the filename, it could do nothing useful with it.
>>
>> ??? It must know the encoding in order to handle the file properly.
> 
> Ah! Finally you seem to understand where the problem is!
> 
> Ada.Text_IO would have to know the encoding, but it doesn't.

See s-fileio.adb, lines 845-857.

>>> Universal_Integer is a pseudo-type.
>>
>> With pseudo-values and pseudo-operations used by pseudo-programmers? (:-))
> 
> All objects of that type are constant. All operations are evaluated at 
> compile time.

This is wrong. See 3.5.5(2) as an example of a non-static function
returning Universal_Integer.

That Universal_Integer leaks allows writing quite strange programs, e.g.
ones using 'Pos attribute in order to perform run-time computations in
universal arithmetic. Beware, that this is not portable, of course.
Universal integer is constrained at run time.

>> Universal types leak into
>> run time through attributes. I.e. you do have objects of universal types at
>> run time in expressions like
>>
>>   Integer'Pos (X) * 2
> 
> You just used the already existing object 2 of type constant 
> Universal_Integer.

   Integer'Pos (X) * Integer'Pos (Y)

> Even if you ignore the "constant", there is no 
> *definition* (or *declaration*) of an object O: Universal_Integer.

Universal_Integer and other numeric types can be mixed in arithmetic and
other operations. Period.

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



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

* Re: Is this expected behavior or not
  2013-04-08 19:08                                                                                                                                     ` Dmitry A. Kazakov
@ 2013-04-09  7:18                                                                                                                                       ` Stefan.Lucks
  2013-04-09  8:17                                                                                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-09  7:18 UTC (permalink / raw)


On Mon, 8 Apr 2013, Dmitry A. Kazakov wrote:

>> Ada.Text_IO would have to know the encoding, but it doesn't.
>
> See s-fileio.adb, lines 845-857.

Cool! I haven't been aware of that. Starting with line 483:

          if V1 = 0 then
             Encoding := CRTL.Unspecified;

          elsif Formstr (V1 .. V2) = "utf8" then
             Encoding := CRTL.UTF8;

          elsif Formstr (V1 .. V2) = "8bits" then
             Encoding := CRTL.ASCII_8bits;

          else
             raise Use_Error with "invalid Form";
          end if;

So the GNAT implementation of Ada.Text_IO can distinguish between 
Unspecified, UTF8 and ASCII-8bits. This is more than I would have 
expected. But it not really useful. Apart from the portability issue (what 
are the standard libs of other compilers doing?), there are a hell of 
different encodings your filesystem might use. There is old CP437 from 
MS-DOS time, there are more than ten different ISO 8859 encodings, ...

A special technical issue is that the encoding of the fully qualified 
filename can change even *within* the string itself -- the first part of 
the path is using the encoding of the root filesystem, while the rest uses 
the encoding of the filesystem itself. In practice, this is mostly 
harmless, since the first part typically looks like "/media/disk/" or 
"/dev/sdb5", using only characters which are invariant under most common 
encodings. But this still shows that the idea of letting Ada.Text_IO 
dealing with the encoding will get you only so far.

>> compile time.
>
> This is wrong. See 3.5.5(2) as an example of a non-static function
> returning Universal_Integer.

Well, the authors of the standard can use "standard definition magic" to 
define such a function, but the author of an Ada program cannot. There is 
no type with name Universal_Integer in Ada programs, and any attempt to 
define one will, at best, overload the name of Universal_Integer, but 
never give you the type that the standard denotes as Universal_Integer.

>> You just used the already existing object 2 of type constant
>> Universal_Integer.
>
>   Integer'Pos (X) * Integer'Pos (Y)

Language lawyers may correct me, but if X and Y are not static, I would 
expect Integer'Pos(X) and Integer'Pos(Y) to be converted to the expected 
result type even before the multiplication has been called.

> Universal_Integer and other numeric types can be mixed in arithmetic and
> other operations. Period.

Again, my understanding is that they are converted before any run-time 
operation is performed.


------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--



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

* Re: Is this expected behavior or not
  2013-04-09  7:18                                                                                                                                       ` Stefan.Lucks
@ 2013-04-09  8:17                                                                                                                                         ` Dmitry A. Kazakov
  2013-04-09 15:20                                                                                                                                           ` Stefan.Lucks
  2013-04-09 22:57                                                                                                                                           ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-09  8:17 UTC (permalink / raw)


On Tue, 9 Apr 2013 09:18:09 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Mon, 8 Apr 2013, Dmitry A. Kazakov wrote:
> 
>>> Ada.Text_IO would have to know the encoding, but it doesn't.
>>
>> See s-fileio.adb, lines 845-857.
> 
> Cool! I haven't been aware of that. Starting with line 483:
> 
>           if V1 = 0 then
>              Encoding := CRTL.Unspecified;
> 
>           elsif Formstr (V1 .. V2) = "utf8" then
>              Encoding := CRTL.UTF8;
> 
>           elsif Formstr (V1 .. V2) = "8bits" then
>              Encoding := CRTL.ASCII_8bits;
> 
>           else
>              raise Use_Error with "invalid Form";
>           end if;
> 
> So the GNAT implementation of Ada.Text_IO can distinguish between 
> Unspecified, UTF8 and ASCII-8bits. This is more than I would have 
> expected. But it not really useful.

Of course it is useful because text files have different encoding.

> Apart from the portability issue (what 
> are the standard libs of other compilers doing?), there are a hell of 
> different encodings your filesystem might use. There is old CP437 from 
> MS-DOS time, there are more than ten different ISO 8859 encodings, ...

This is why string types SHALL be designed properly in order to handle this
without introducing millions of I/O packages.
 
> A special technical issue is that the encoding of the fully qualified 
> filename can change even *within* the string itself -- the first part of 
> the path is using the encoding of the root filesystem, while the rest uses 
> the encoding of the filesystem itself.

File name is not a string in first place. Ada.Directory and other I/O
packages are broken in that respect, but that is irrelevant here.

>>> compile time.
>>
>> This is wrong. See 3.5.5(2) as an example of a non-static function
>> returning Universal_Integer.
> 
> Well, the authors of the standard can use "standard definition magic" to 
> define such a function, but the author of an Ada program cannot.

You cannot do

   X : String;

either. String is a pseudo-type? Is it RM terminology? (:-))

Now consider Ada.Strings.Unbounded. It has a whole lot of mixed string type
operation declared: Append, "&", "=", "<", ">", ">=", "<=". Now as we
learned that String is "pseudo-type," it would be OK to mix. Right? But
then, what is the buzz? If string types are pseudo-type we can mix them
happily anyway!  (:-))

>>> You just used the already existing object 2 of type constant
>>> Universal_Integer.
>>
>>   Integer'Pos (X) * Integer'Pos (Y)
> 
> Language lawyers may correct me, but if X and Y are not static, I would 
> expect Integer'Pos(X) and Integer'Pos(Y) to be converted to the expected 
> result type even before the multiplication has been called.

   Character'Val (Integer'Pos (X) * Long_Integer'Pos (Y))

>> Universal_Integer and other numeric types can be mixed in arithmetic and
>> other operations. Period.
> 
> Again, my understanding is that they are converted before any run-time 
> operation is performed.

Wrong but irrelevant as well, because semantically there is no difference. 

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



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

* Re: Is this expected behavior or not
  2013-04-09  8:17                                                                                                                                         ` Dmitry A. Kazakov
@ 2013-04-09 15:20                                                                                                                                           ` Stefan.Lucks
  2013-04-09 16:15                                                                                                                                             ` Dmitry A. Kazakov
  2013-04-09 22:59                                                                                                                                             ` Randy Brukardt
  2013-04-09 22:57                                                                                                                                           ` Randy Brukardt
  1 sibling, 2 replies; 242+ messages in thread
From: Stefan.Lucks @ 2013-04-09 15:20 UTC (permalink / raw)


On Tue, 9 Apr 2013, Dmitry A. Kazakov wrote:

> This is why string types SHALL be designed properly in order to handle this
> without introducing millions of I/O packages.

We are in violent agreement here. The question is how much compatibility 
is needed between a new string type and the gazillions of old and broken 
ones, not that strings SHOULD be designed properly ...

> File name is not a string in first place. Ada.Directory and other I/O
> packages are broken in that respect, but that is irrelevant here.

It was you who came up with the example of Ada.Text_IO.Open, not me.

> You cannot do
>
>   X : String;
>
> either. String is a pseudo-type?

This is a straw man argument. String is not pseudo.

As you know very well, you can do X: String := ... or X: String(A ..B), 
while you can't do anything similar for Universal_Integer.

>> Again, my understanding is that they are converted before any run-time
>> operation is performed.
>
> Wrong but irrelevant as well, because semantically there is no difference.

OK, so look at the semantic. Different semantic means the same operation 
with the same inputs behave differently.

The following program fragment nicely prints "Smaller or Equal":

     if  ((Character'Pos('z') ** Character'Pos('z'))
        > (Character'Pos('z') ** Character'Pos('z')))
     then
        Put_Line("Larger");
     else
        Put_Line("Smaller or Equal");
     end if;

This is really cool -- the sematic of Universal_Integer enables us to 
perform operations over huge integers without overflows.

Now, guess what the following program fragment does?

      S: String := "zzzz";

   begin

     if  ((Character'Pos(S(1)) ** Character'Pos(S(3)))
        > (Character'Pos(S(2)) ** Character'Pos(S(4))))
     then
        Put_Line("More");
     else
        Put_Line("Less or Equal");
     end if;

The output is neither "More" nor "Less or Equal" but
"raised CONSTRAINT_ERROR : arit64.c:52 overflow check failed".

(When using gnat, don't forget "-gnato" to switch on overflow checks.)

Whenever the compiler cannot statically evaluate expressions of type 
Universal_Integer it switches to run time arithmetic over some integer 
type available at run time. This means, the expression behaves according 
to that type's semantic, raising Constraint_Error on overflows included.

If you insist that all the operations (such as the "**") above are over 
Universal_Integer, than that would mean the semantic of Universal_Integer
is allowed to change, depending on compile. versus run time.

That would be even more "pseudo". ;-)


------  I  love  the  taste  of  Cryptanalysis  in  the morning!  ------
     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
--Stefan.Lucks (at) uni-weimar.de, Bauhaus-Universität Weimar, Germany--



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

* Re: Is this expected behavior or not
  2013-04-09 15:20                                                                                                                                           ` Stefan.Lucks
@ 2013-04-09 16:15                                                                                                                                             ` Dmitry A. Kazakov
  2013-04-09 22:59                                                                                                                                             ` Randy Brukardt
  1 sibling, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-09 16:15 UTC (permalink / raw)


On Tue, 9 Apr 2013 17:20:35 +0200, Stefan.Lucks@uni-weimar.de wrote:

> On Tue, 9 Apr 2013, Dmitry A. Kazakov wrote:
> 
>> You cannot do
>>
>>   X : String;
>>
>> either. String is a pseudo-type?
> 
> This is a straw man argument. String is not pseudo.

Universal_Integer is neither.
 
>>> Again, my understanding is that they are converted before any run-time
>>> operation is performed.
>>
>> Wrong but irrelevant as well, because semantically there is no difference.
> 
> OK, so look at the semantic. Different semantic means the same operation 
> with the same inputs behave differently.
> 
> The following program fragment nicely prints "Smaller or Equal":
> 
>      if  ((Character'Pos('z') ** Character'Pos('z'))
>         > (Character'Pos('z') ** Character'Pos('z')))
>      then
>         Put_Line("Larger");
>      else
>         Put_Line("Smaller or Equal");
>      end if;
> 
> This is really cool -- the sematic of Universal_Integer enables us to 
> perform operations over huge integers without overflows.

It does not, the range of Universal_Integer at run-time is
implementation-dependent.
 
-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Is this expected behavior or not
  2013-04-08  8:59                                                                                                                                 ` Dmitry A. Kazakov
  2013-04-08 15:35                                                                                                                                   ` Stefan.Lucks
@ 2013-04-09 22:45                                                                                                                                   ` Randy Brukardt
  2013-04-10  7:37                                                                                                                                     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-09 22:45 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:imfrovuxjjo6.6ebpr0pq5kgr.dlg@40tude.net...
...
>> You cannot define an object O:
>> Universal_Integer, neither a function returning Universal_Integer ...
>
> As if it were relevant. But you are wrong here. Universal types leak into
> run time through attributes. I.e. you do have objects of universal types 
> at
> run time in expressions like
>
>   Integer'Pos (X) * 2

A major design flaw of the language, IMHO. Run-time universal operations are 
nonsense; they have completely different semantics than the compile-time 
version -- which is dangerous as well as confusing. The run-time version is 
really just Long_Integer with dangerous implicit conversions. A step 
backwards.

Stefan has it right (even if Ada doesn't): Universal integer is a 
pseudo-type that only should have an existence to the compiler.

                             Randy.


                                  Randy.






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

* Re: Is this expected behavior or not
  2013-04-08 15:35                                                                                                                                   ` Stefan.Lucks
  2013-04-08 19:08                                                                                                                                     ` Dmitry A. Kazakov
@ 2013-04-09 22:53                                                                                                                                     ` Randy Brukardt
  1 sibling, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-04-09 22:53 UTC (permalink / raw)


<Stefan.Lucks@uni-weimar.de> wrote in message 
news:alpine.DEB.2.02.1304081709350.8693@debian...
On Mon, 8 Apr 2013, Dmitry A. Kazakov wrote:

>>> Because even if the implementation of Ada.Text_IO.Open would know the
>>> encoding of the filename, it could do nothing useful with it.
>>
>> ??? It must know the encoding in order to handle the file properly.
>
>Ah! Finally you seem to understand where the problem is!
>
>Ada.Text_IO would have to know the encoding, but it doesn't.

Of course it does, the encoding is 8-bit Latin-1 (in the absence of any 
implementation-defined stuff). If you want UCS-16, use Wide_Text_IO. The 
name of the package chooses the representation.

Ada doesn't really support any other encodings than these.

> So it just treats the string like a sequence of bytes (much like a 
> C-string) and
> leaves it to the Application Programmer to apply the proper conversion
> before. Which means, the conversion must be done explicitly.

You can do that, but (a) it's not really true (Text_IO has to know about LF 
and CR and FF to deal with line endings and the like) - you get lucky with 
UTF-8 because the representation of those is the same as Latin-1; (b) 
conversions are expensive.

It would be more appropriate to use a stream solution for non-Latin-1 
representations, but that of course has it's own problems.

Probably the best we can do today (Text_IO is going nowhere) is a 
combination of Root_String'Class operations (so that the *program* 
representation is irrelevant) and form parameters to specify file 
representation. I don't see any real problems with that.

                                        Randy.





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

* Re: Is this expected behavior or not
  2013-04-09  8:17                                                                                                                                         ` Dmitry A. Kazakov
  2013-04-09 15:20                                                                                                                                           ` Stefan.Lucks
@ 2013-04-09 22:57                                                                                                                                           ` Randy Brukardt
  2013-04-10  7:30                                                                                                                                             ` Dmitry A. Kazakov
  2013-04-10  8:00                                                                                                                                             ` Root_String'Class? (Was: Is this expected behavior or not) Jacob Sparre Andersen
  1 sibling, 2 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-04-09 22:57 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:ihi0ajan1ehu.iplgjkwsfpii.dlg@40tude.net...
...
> Now consider Ada.Strings.Unbounded. It has a whole lot of mixed string 
> type
> operation declared: Append, "&", "=", "<", ">", ">=", "<=".

Yes, a horrible mistake. It prevents Ada.Strings.Unbounded from ever having 
any literals, because they could never have a unique type.

Mixing types = mistake!!

                       Randy.





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

* Re: Is this expected behavior or not
  2013-04-09 15:20                                                                                                                                           ` Stefan.Lucks
  2013-04-09 16:15                                                                                                                                             ` Dmitry A. Kazakov
@ 2013-04-09 22:59                                                                                                                                             ` Randy Brukardt
  1 sibling, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-04-09 22:59 UTC (permalink / raw)


<Stefan.Lucks@uni-weimar.de> wrote in message 
news:alpine.DEB.2.02.1304091606430.12289@debian...
...
> If you insist that all the operations (such as the "**") above are over
> Universal_Integer, than that would mean the semantic of Universal_Integer
> is allowed to change, depending on compile. versus run time.

Unfortunately, that is mandated by Ada.

>That would be even more "pseudo". ;-)

Darn right.

                          Randy. 





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

* Re: Is this expected behavior or not
  2013-04-07  7:00                                                                                                                 ` Is this expected behavior or not Dmitry A. Kazakov
@ 2013-04-09 23:24                                                                                                                   ` Randy Brukardt
  2013-04-10  8:20                                                                                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-09 23:24 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:igo6blwn0oas$.wifvpq91hm9m.dlg@40tude.net...
> On Fri, 5 Apr 2013 20:20:58 -0500, Randy Brukardt wrote:
...
> You conflate type checking with representation checking. There is no need
> to check how a string is represented.

That's because they're intimately linked. You can't do an operation without 
knowing how the type is represented. And you should never mix types. Since 
you seem to think that mixing types is a good thing, you need to find a 
language where that's possible. Ada is never going to be that language.

...
> You will need explicit conversions wherever you use Get_Text:
>
>      X : UTF8_String := Box.Get_Text;
>
> or
>
>      Open (Box.Get_Text);

You wouldn't have to in either of these cases (presuming that Open has a 
specific type). But of course you could get a type mismatch that way (it 
would be better when the tag is passed up, as accessibility is). But in 
general it's a good thing to specify your types, and you do that with 
explicit conversions.

...
>> Well, I have. As I previously explained, the abstract routines and 
>> functions
>> in the Claw Builder root types make it so time-consuming to create an
>> extension (the last one I did took around 20 hours to write, and even 
>> then I
>> never finished it) that it's impractical to do so.
>>
>> If you have only one such routine,
>
> Why there should be many?

If you've got operations like "+" or "*", you'll have a lot of functions 
returning objects of the type. That's a bad idea for the reasons I 
mentioned.

> Anyway, if you know how to create such function, you make it class-wide. 
> If
> you don't know, nobody knows. It must be overridden and the compiler tells
> you so. There is simply no problem with that.

Of course there is a problem with that -- if it takes more than a couple of 
hours to create those functions, you cannot write an extension in a working 
day (and anything else is too long). I agree that there's probably going to 
have to be one constructor function, but that's about all that can be 
tolerated. And, similarly, abstract routines can be tolerated only in very 
small doses -- no giant interfaces being inherited.

....
>>> Yes, the language permits compilers implemented poorly, and?
>>
>> This has nothing to do with compilers. It has to do with *poorly designed
>> programs*. It's certainly true that a program that depends on by-copy or
>> by-reference passing is wrong; the compiler should be free to choose. But
>> this is an undetectable error. And bringing Adjust into it makes it much
>> worse, because it's easy to write code that doesn't work if Adjust is 
>> called
>> (you probably can get infinite recursion that way).
>
> Are you saying the copy constructors (Adjust) are broken in Ada? They are
> to me too. Fix them.

Not at all (at least for this topic). The act of calling a routine (*any 
routine*) usually has detectable side-effects. That's certainly true for 
Adjust. (It might be bad practice to depend on those side-effects, but 
language standards cannot legislate program morality.) It cannot be the case 
that moving a program to a different compiler breaks a *correct* program 
simply because the new compiler now calls (or does not call) Adjust.

We call this "performance incompability"; we can't change the language in 
such a way that the performance of existing programs is going to change a 
lot -- doing so has a serious potential for breakage (for instance, it might 
cause or expose a race condition).

>>>>>> It strikes me that the model of stripping tags means that type 
>>>>>> conversion
>>>>>> of an object to a class-wide type would effectively change the tag 
>>>>>> (if the
>>>>>> routine was inherited or called by a conversion of an operand).
>>>>>
>>>>> Yes, re-dispatch is a broken thing. Don't do it, because it is 
>>>>> ambiguous
>>>>> in general case when objects do not have an identity. By-copy scalar 
>>>>> types
>>>>> are such things. There is nothing which could distinguish Integer 13 
>>>>> from
>>>>> Long_Integer 13 except the context. Once you dispatched that 
>>>>> information
>>>>> is lost. There is no way back.
>>
>> Here you are saying that you can't redispatch because you insist on a 
>> model
>> that doesn't allow it.
>
> No model exist which would allow re-dispatch on scalar value. Like no 
> model
> exist where 2+2=5.

Gee, you can easily redefine "+" in Ada so that 2 + 2 = 5 -- indeed, I 
believe that one of the ACATS tests does exactly that. Sure seems like the 
Ada model includes that!

I have an tagged universal numeric type implementation, and it certainly 
allows redispatch. It's not much of a leap to think of it as a scalar type.

>>>>>> That would
>>>>>> mean that the behavior of such a conversion would be very different 
>>>>>> for
>>>>>> an untagged type and for a tagged type.
>>>>>
>>>>> Not different. It is just so that tagged types per design have type
>>>>> identity. Other types simply don't have it.
>>>>
>>>> Objects of limited types are always assumed to have an identity;
>>>
>>> No. E.g. task and protected types lack type identity. Only tagged types
>>> have type identity.
>>>
>>> Note that type identity /= object identity (e.g. machine address where 
>>> the
>>> object resides).
>>
>> I don't think that they ought to be separated. If you have object 
>> identity,
>> and every object has a nominal type, it does not make sense to lose that
>> information.
>
> Nothing is lost. You forgot that the parameter was passed by copy, as
> required by the type, which was by-copy. It is another object in there. 
> Its
> identity is obviously not the identity of the origin. How could it be
> otherwise?

You can't pass types with object identity by-copy. (These are "immutably 
limited".) So the issue does not come up. Next question??

>>>>> You want to derive each string type straight from Root_String.
>>>>
>>>> Yes, or from related ones. There is no significant value to doing 
>>>> anything
>>>> else - as you point out, if you can inherit the operations, the
>>>> representations have to be compatible. So there is nothing useful you 
>>>> can
>>>> do with multiple levels.
>>>
>>> Encoding!
>>
>> You have to reimplement *every* operation for a new representation (in 
>> your
>> model as well as in existing Ada).
>
> Most bodies will be inherited per composition with conversion.

I forget that you seem to think that compilers will magically be able to 
implement this stuff as if you wrote it by hand. That isn't very likely to 
happen. The only way to define these conversions would be through a 
Wide_Wide_String intermediate - the net effect is that the conversions will 
be quite expensive and you would never, ever want to use such 
implementations. (Certainly not for any commonly used operations, and the 
others ought to be class-wide anyway, stuff like Find_Token) You're going to 
write all-new implementations for each representation, there won't be 
anything worth inheriting.

                                             Randy.





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

* Re: Is this expected behavior or not
  2013-04-09 22:57                                                                                                                                           ` Randy Brukardt
@ 2013-04-10  7:30                                                                                                                                             ` Dmitry A. Kazakov
  2013-04-10  8:00                                                                                                                                             ` Root_String'Class? (Was: Is this expected behavior or not) Jacob Sparre Andersen
  1 sibling, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-10  7:30 UTC (permalink / raw)


On Tue, 9 Apr 2013 17:57:55 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:ihi0ajan1ehu.iplgjkwsfpii.dlg@40tude.net...
> ...
>> Now consider Ada.Strings.Unbounded. It has a whole lot of mixed string 
>> type operation declared: Append, "&", "=", "<", ">", ">=", "<=".
> 
> Yes, a horrible mistake. It prevents Ada.Strings.Unbounded from ever having 
> any literals, because they could never have a unique type.

Overloading is what leads to problems. There are ways to resolve it. One
approach could be literal extension. Usually it is thought that
Wide_Character is a constrained Wide_Wide_Character and Character is a
constrained Wide_Character:

  Wide_Wide_Character -> Wide_Character -> Character

This cases corresponding values to overlap:

   'A' is either Wide_Wide_Character or Wide_Character or Character

One could consider an alternative derivation based on enumeration
extension:

  Character -> Wide_Character -> Wide_Wide_Character

That would remove overloading of literals. 'A' will be Character only.

The reason why this did not work in Ada was due to lack of multi-methods.
Ada character/string operations were all overloaded, so in order to make
them work with literals, one had to overload literals as well.

With multi-methods there will be no need to overload literals anymore:

   X : Wide_Character := 'A'; -- This is OK with multi-method

Resolved to

   procedure ":=" (Left : in out Wide_Character; Right : Character);

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



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

* Re: Is this expected behavior or not
  2013-04-09 22:45                                                                                                                                   ` Randy Brukardt
@ 2013-04-10  7:37                                                                                                                                     ` Dmitry A. Kazakov
  2013-04-10 22:15                                                                                                                                       ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-10  7:37 UTC (permalink / raw)


On Tue, 9 Apr 2013 17:45:24 -0500, Randy Brukardt wrote:

> Stefan has it right (even if Ada doesn't): Universal integer is a 
> pseudo-type that only should have an existence to the compiler.

This is what happens when theories face reality. You are ready to declare
Ada design wrong in order to save the theory. (:-))

As an exercise compare how much of Ada design is wrong according to your
theory vs. mine?

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



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

* Root_String'Class? (Was: Is this expected behavior or not)
  2013-04-09 22:57                                                                                                                                           ` Randy Brukardt
  2013-04-10  7:30                                                                                                                                             ` Dmitry A. Kazakov
@ 2013-04-10  8:00                                                                                                                                             ` Jacob Sparre Andersen
  2013-04-10 21:48                                                                                                                                               ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Jacob Sparre Andersen @ 2013-04-10  8:00 UTC (permalink / raw)


Randy Brukardt wrote:

[ many interesting things about string types ]

You mention creating an abstract tagged Root_String type and deriving
actual string types from it.  Do you have some concrete ideas for how
you would do it?  Could it be done with what we have in Ada 2012?  Or
would it require some extensions to the language?

Greetings,

Jacob
-- 
�When Roman engineers built a bridge, they had to stand under it while
 the first legion marched across. If programmers today worked under
 similar ground rules, they might well find themselves getting much more
 interested in Ada!�                                     -- Robert Dewar



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

* Re: Is this expected behavior or not
  2013-04-09 23:24                                                                                                                   ` Randy Brukardt
@ 2013-04-10  8:20                                                                                                                     ` Dmitry A. Kazakov
  2013-04-10 22:07                                                                                                                       ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-10  8:20 UTC (permalink / raw)


On Tue, 9 Apr 2013 18:24:29 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:igo6blwn0oas$.wifvpq91hm9m.dlg@40tude.net...
>> On Fri, 5 Apr 2013 20:20:58 -0500, Randy Brukardt wrote:
> ...
>> You conflate type checking with representation checking. There is no need
>> to check how a string is represented.
> 
> That's because they're intimately linked. You can't do an operation without 
> knowing how the type is represented.

That does not explain why representation needs to be checked. Especially
for the types like Boolean and Integer.

>>> Well, I have. As I previously explained, the abstract routines and functions
>>> in the Claw Builder root types make it so time-consuming to create an
>>> extension (the last one I did took around 20 hours to write, and even 
>>> then I never finished it) that it's impractical to do so.
>>>
>>> If you have only one such routine,
>>
>> Why there should be many?
> 
> If you've got operations like "+" or "*", you'll have a lot of functions 
> returning objects of the type. That's a bad idea for the reasons I 
> mentioned.

You have + and * of GUI objects? That is weird. Anyway if you have
arithmetic upon a hierarchy how the compiler is supposed to deduce
implementations for derived types?

>>>> Yes, the language permits compilers implemented poorly, and?
>>>
>>> This has nothing to do with compilers. It has to do with *poorly designed
>>> programs*. It's certainly true that a program that depends on by-copy or
>>> by-reference passing is wrong; the compiler should be free to choose. But
>>> this is an undetectable error. And bringing Adjust into it makes it much
>>> worse, because it's easy to write code that doesn't work if Adjust is 
>>> called (you probably can get infinite recursion that way).
>>
>> Are you saying the copy constructors (Adjust) are broken in Ada? They are
>> to me too. Fix them.
> 
> Not at all (at least for this topic). The act of calling a routine (*any 
> routine*) usually has detectable side-effects. That's certainly true for 
> Adjust. (It might be bad practice to depend on those side-effects, but 
> language standards cannot legislate program morality.)

You don't make language design dependent and promoting bad practices.

>>>>>>> It strikes me that the model of stripping tags means that type conversion
>>>>>>> of an object to a class-wide type would effectively change the tag (if the
>>>>>>> routine was inherited or called by a conversion of an operand).
>>>>>>
>>>>>> Yes, re-dispatch is a broken thing. Don't do it, because it is ambiguous
>>>>>> in general case when objects do not have an identity. By-copy scalar 
>>>>>> types are such things. There is nothing which could distinguish Integer 13 
>>>>>> from Long_Integer 13 except the context. Once you dispatched that 
>>>>>> information is lost. There is no way back.
>>>
>>> Here you are saying that you can't redispatch because you insist on a 
>>> model that doesn't allow it.
>>
>> No model exist which would allow re-dispatch on scalar value. Like no 
>> model exist where 2+2=5.
> 
> Gee, you can easily redefine "+" in Ada so that 2 + 2 = 5 -- indeed,

Then don't expect arithmetic to work. There is a price for each wrong
decision.

> I have an tagged universal numeric type implementation, and it certainly 
> allows redispatch. It's not much of a leap to think of it as a scalar type.

It is a huge leap, it is from semantically right to wrong. Scalar objects
do not have identity, which is a fundamental properly of. Pretty much is
based on lack of identity, these properties allow vital program analysis,
transformations, e.g. optimization etc. The major flaw of OOPL is an
attempt to hand identity on all types. This is simply impossible to do.
This is why all of them, including Ada, have types which are more types
then others.
 
>>>>>>> That would
>>>>>>> mean that the behavior of such a conversion would be very different 
>>>>>>> for an untagged type and for a tagged type.
>>>>>>
>>>>>> Not different. It is just so that tagged types per design have type
>>>>>> identity. Other types simply don't have it.
>>>>>
>>>>> Objects of limited types are always assumed to have an identity;
>>>>
>>>> No. E.g. task and protected types lack type identity. Only tagged types
>>>> have type identity.
>>>>
>>>> Note that type identity /= object identity (e.g. machine address where 
>>>> the object resides).
>>>
>>> I don't think that they ought to be separated. If you have object identity,
>>> and every object has a nominal type, it does not make sense to lose that
>>> information.
>>
>> Nothing is lost. You forgot that the parameter was passed by copy, as
>> required by the type, which was by-copy. It is another object in there. 
>> Its identity is obviously not the identity of the origin. How could it be
>> otherwise?
> 
> You can't pass types with object identity by-copy.

And untagged by-copy types will have none, per design.

>>>>>> You want to derive each string type straight from Root_String.
>>>>>
>>>>> Yes, or from related ones. There is no significant value to doing anything
>>>>> else - as you point out, if you can inherit the operations, the
>>>>> representations have to be compatible. So there is nothing useful you 
>>>>> can do with multiple levels.
>>>>
>>>> Encoding!
>>>
>>> You have to reimplement *every* operation for a new representation (in 
>>> your model as well as in existing Ada).
>>
>> Most bodies will be inherited per composition with conversion.
> 
> I forget that you seem to think that compilers will magically be able to 
> implement this stuff as if you wrote it by hand.

Not at all. The conversion will be provided by the programmer. If he did
not define one, he will be required to override things manually.

> That isn't very likely to 
> happen. The only way to define these conversions would be through a 
> Wide_Wide_String intermediate - the net effect is that the conversions will 
> be quite expensive and you would never, ever want to use such 
> implementations.

This is exactly the overhead of doing this using the infamous unary plus
operation. I don't understand the point you are trying to make. You don't
want to override for custom types, you don't want automatic conversion as
too expensive. There is no third way. You want to apply explicit
conversions at all call points? This is exactly the solution you declared
inefficient. It not only inefficient, it is extremely error prone and a
major overhead for those unfortunate who have to use the package defined in
such manner. The compiler rejects a program. What you do? Erratically place
unary pluses before all arguments? But that is invisible. Actually some
hundred of them are already visible. For each of them the compiler spits
some garbage error messages on you. But the right one you need is not
visible. Were was it declared? Was it declared anywhere? Have fun!

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



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

* Re: Root_String'Class? (Was: Is this expected behavior or not)
  2013-04-10  8:00                                                                                                                                             ` Root_String'Class? (Was: Is this expected behavior or not) Jacob Sparre Andersen
@ 2013-04-10 21:48                                                                                                                                               ` Randy Brukardt
  0 siblings, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-04-10 21:48 UTC (permalink / raw)


"Jacob Sparre Andersen" <sparre@nbi.dk> wrote in message 
news:8761zuizmq.fsf_-_@adaheads.sparre-andersen.dk...
> Randy Brukardt wrote:
>
> [ many interesting things about string types ]
>
> You mention creating an abstract tagged Root_String type and deriving
> actual string types from it.  Do you have some concrete ideas for how
> you would do it?  Could it be done with what we have in Ada 2012?  Or
> would it require some extensions to the language?

There is a rough proposal in the body of AI12-0021-1/01. Please note that 
this is completely my invention which has not be vetted by anyone.

The only needed magic is to allow string literals for the root type. 
Everything else needed is already provided by Ada 2012. (Note that I turned 
slices into functions, we'd need an extra facility to support the slice 
syntax. I don't find that important enough to bother with, but perhaps 
others will disagree.) Most of the less-primitive operations would primarily 
be supported via Ada.Strings.General (which would be similar in contents to 
Ada.Strings.Fixed). One imagines that types similar to Unbounded_String and 
Bounded_Striing would also be provided as members of Root_String'Class, so 
they would have much smaller packages and would be much more interoperable.

The downside is that elements would be accessed as Wide_Wide_Characters, 
which in some cases (16-bit processors, for instance) would make things more 
expensive than currently. And of course, a lot more dispatching.

                                    Randy.





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

* Re: Is this expected behavior or not
  2013-04-10  8:20                                                                                                                     ` Dmitry A. Kazakov
@ 2013-04-10 22:07                                                                                                                       ` Randy Brukardt
  2013-04-11  7:59                                                                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-10 22:07 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:8bj2k30k7i19.w7ehsldwbf7x.dlg@40tude.net...
> On Tue, 9 Apr 2013 18:24:29 -0500, Randy Brukardt wrote:
...
>>> Why there should be many?
>>
>> If you've got operations like "+" or "*", you'll have a lot of functions
>> returning objects of the type. That's a bad idea for the reasons I
>> mentioned.
>
> You have + and * of GUI objects? That is weird. Anyway if you have
> arithmetic upon a hierarchy how the compiler is supposed to deduce
> implementations for derived types?

Tagged types and extension is used for more than just GUIs. The compiler 
shouldn't have trouble with inheriting implementations -- we don't do or 
want multi-methods, after all. Ada only supports that for null extensions; 
it's easy to extend that so long as an information-preserving conversion is 
possible. (That would have to be declared by an aspect, I think.)

...
>>>>> Yes, the language permits compilers implemented poorly, and?
>>>>
>>>> This has nothing to do with compilers. It has to do with *poorly 
>>>> designed
>>>> programs*. It's certainly true that a program that depends on by-copy 
>>>> or
>>>> by-reference passing is wrong; the compiler should be free to choose. 
>>>> But
>>>> this is an undetectable error. And bringing Adjust into it makes it 
>>>> much
>>>> worse, because it's easy to write code that doesn't work if Adjust is
>>>> called (you probably can get infinite recursion that way).
>>>
>>> Are you saying the copy constructors (Adjust) are broken in Ada? They 
>>> are
>>> to me too. Fix them.
>>
>> Not at all (at least for this topic). The act of calling a routine (*any
>> routine*) usually has detectable side-effects. That's certainly true for
>> Adjust. (It might be bad practice to depend on those side-effects, but
>> language standards cannot legislate program morality.)
>
> You don't make language design dependent and promoting bad practices.

If you are starting with a blank page, you're right. If you are building on 
30+ years of practice, even "bad practice" has to be taken into account. 
This is one of the reasons that the language you're suggesting really has to 
be different than Ada. Ada has too many existing nasties that have to be 
preserved in order to make the overhaul you're suggesting. We'd be afraid to 
do it even if it appears to be neutral, just because it would be too risky 
to make the change.

I'd like to make objects [and exceptions] overloadable (it would fix a large 
percentage of the problems with use clauses and visibility, and unify 
objects, enumeration literals, and functions - which you should be able to 
switch between without breaking anything). But the idea is deemed too risky; 
there is a very low possibility of silent changes in meaning of programs 
(usually, an illegal program would become legal -- not a problem, or a legal 
program would become illegal -- a problem, but not showstopping, especially 
as it would be rare). So the idea is unlikely to go anywhere. And that is a 
*much* simpler change than what you're suggesting.

...
...
>> That isn't very likely to
>> happen. The only way to define these conversions would be through a
>> Wide_Wide_String intermediate - the net effect is that the conversions 
>> will
>> be quite expensive and you would never, ever want to use such
>> implementations.
>
> This is exactly the overhead of doing this using the infamous unary plus
> operation. I don't understand the point you are trying to make. You don't
> want to override for custom types, you don't want automatic conversion as
> too expensive. There is no third way. You want to apply explicit
> conversions at all call points? This is exactly the solution you declared
> inefficient. It not only inefficient, it is extremely error prone and a
> major overhead for those unfortunate who have to use the package defined 
> in
> such manner. The compiler rejects a program. What you do? Erratically 
> place
> unary pluses before all arguments? But that is invisible. Actually some
> hundred of them are already visible. For each of them the compiler spits
> some garbage error messages on you. But the right one you need is not
> visible. Were was it declared? Was it declared anywhere? Have fun!

You're confusing expensive *implicit* operations with expensive explicit 
ones. I don't care that an explicit type conversion is expensive -- you 
wrote it, you meant it, and you can see the consequences -- it's right there 
in the source code.

You're right that you could use unary plus for this purpose -- a lot of 
people do -- but it's also considered an ugly hack. I would never use it to 
cover up expensive conversions -- I *want* those hard to write, so I only 
write them where absolutely necessary. And the use of "+" fills your program 
with ambiguity. OTOH, writing explicit conversions (or function calls with 
real names) does not have this problem.

For instance, I tend to write out the entire name of the conversion between 
string and unbounded string:

    Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));

I've used the "+" trick here, but almost exclusively for literals (which 
should have been part of the type from the beginning).

                                     Randy.






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

* Re: Is this expected behavior or not
  2013-04-10  7:37                                                                                                                                     ` Dmitry A. Kazakov
@ 2013-04-10 22:15                                                                                                                                       ` Randy Brukardt
  2013-04-11  7:33                                                                                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-10 22:15 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:dqljoxvn36my.xkv88psqukp9$.dlg@40tude.net...
> On Tue, 9 Apr 2013 17:45:24 -0500, Randy Brukardt wrote:
>
>> Stefan has it right (even if Ada doesn't): Universal integer is a
>> pseudo-type that only should have an existence to the compiler.
>
> This is what happens when theories face reality. You are ready to declare
> Ada design wrong in order to save the theory. (:-))

Yup. Because it is, and the theory works well. :-)

I certainly don't believe Ada is perfect, and some parts of it are screwed 
up and much more complex than necessary. I'd love to make an Ada-like 
language that had fewer warts. But blowing up its models and starting over 
would certainly introduce a new set of warts because of not understanding 
all of the issues very well. Staying as close as possible to the existing 
models lets us build on the existing experience (and for Ada itself, is 
absolutely necessary).

> As an exercise compare how much of Ada design is wrong according to your
> theory vs. mine?

So far as I know, run-time universals and the occassional mixed type 
operation is it. I'd dump some features of Ada as insufficiently valuable if 
starting from scratch (visibility in nested units would get a makeover), but 
the design would be largely the same.

You seem to want to completely dump the Ada design in favor of something 
based on multi-methods. Multi-methods are the same as weak typing to me, I 
don't want to see them explicitly or implicitly.

                                              Randy.





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

* Re: Is this expected behavior or not
  2013-04-10 22:15                                                                                                                                       ` Randy Brukardt
@ 2013-04-11  7:33                                                                                                                                         ` Dmitry A. Kazakov
  2013-04-11 22:37                                                                                                                                           ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-11  7:33 UTC (permalink / raw)


On Wed, 10 Apr 2013 17:15:14 -0500, Randy Brukardt wrote:

> You seem to want to completely dump the Ada design in favor of something 
> based on multi-methods.

Nope, I want to reaffirm Ada design in more fundamental terms. I don't want
to change the semantics which is OK to me.

> Multi-methods are the same as weak typing to me, I 
> don't want to see them explicitly or implicitly.

Exactly the opposite. Multi-methods is a strongly typed description of what
the language does anyway. The alternative is overloading proven to work
extremely poor.

The point is that the class [e.g. of string types] is there. You can handle
it ad-hoc using overloading [Ada 95 solution, which is called ad-hoc
polymorphism] Or you can articulate the class explicitly. You do it in your
proposal anyway as Root_String_Type.

In that case there is simply no alternative to multi-methods because n-ary
operations do not have preferable argument. So what are you going to do
with this? You ditch operations, literals, slices. A great theory! 

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



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

* Re: Is this expected behavior or not
  2013-04-10 22:07                                                                                                                       ` Randy Brukardt
@ 2013-04-11  7:59                                                                                                                         ` Dmitry A. Kazakov
  2013-04-11 11:10                                                                                                                           ` Georg Bauhaus
                                                                                                                                             ` (2 more replies)
  0 siblings, 3 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-11  7:59 UTC (permalink / raw)


On Wed, 10 Apr 2013 17:07:57 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:8bj2k30k7i19.w7ehsldwbf7x.dlg@40tude.net...
>> On Tue, 9 Apr 2013 18:24:29 -0500, Randy Brukardt wrote:
> ...
>>>> Why there should be many?
>>>
>>> If you've got operations like "+" or "*", you'll have a lot of functions
>>> returning objects of the type. That's a bad idea for the reasons I
>>> mentioned.
>>
>> You have + and * of GUI objects? That is weird. Anyway if you have
>> arithmetic upon a hierarchy how the compiler is supposed to deduce
>> implementations for derived types?
> 
> Tagged types and extension is used for more than just GUIs.

Tagged types are useless when arithmetic operations get involved. It does
not work with present design, because type hierarchies are not handled for
such operations.

> The compiler shouldn't have trouble with inheriting implementations

type Real is tagged record
   Value : Float;
end record;
function "+" (L, R : Real) return Real;

type Complex is new Real with record
   Img : Float;
end record;

How is the compiler supposed to inherit "+"?

>> You don't make language design dependent and promoting bad practices.
> 
> If you are starting with a blank page, you're right. If you are building on 
> 30+ years of practice, even "bad practice" has to be taken into account.

Nonsense. Bad practice is bad. Longer it lasts bigger is the damage.

> This is one of the reasons that the language you're suggesting really has to 
> be different than Ada.

We already discussed that. I want to preserve Ada semantics. It is you who
wants completely change the way string types are used in Ada.

>>> That isn't very likely to
>>> happen. The only way to define these conversions would be through a
>>> Wide_Wide_String intermediate - the net effect is that the conversions 
>>> will be quite expensive and you would never, ever want to use such
>>> implementations.
>>
>> This is exactly the overhead of doing this using the infamous unary plus
>> operation. I don't understand the point you are trying to make. You don't
>> want to override for custom types, you don't want automatic conversion as
>> too expensive. There is no third way. You want to apply explicit
>> conversions at all call points? This is exactly the solution you declared
>> inefficient. It not only inefficient, it is extremely error prone and a
>> major overhead for those unfortunate who have to use the package defined 
>> in such manner. The compiler rejects a program. What you do? Erratically 
>> place unary pluses before all arguments? But that is invisible. Actually some
>> hundred of them are already visible. For each of them the compiler spits
>> some garbage error messages on you. But the right one you need is not
>> visible. Were was it declared? Was it declared anywhere? Have fun!
> 
> You're confusing expensive *implicit* operations with expensive explicit 
> ones. I don't care that an explicit type conversion is expensive -- you 
> wrote it, you meant it, and you can see the consequences -- it's right there 
> in the source code.

Right, I don't care about performance I care about usability of the
packages. Only when performance becomes a problem I address that. But I
never let performance issues to cripple my design.

But if performance is your concern, you must be the first to go for
multi-methods, because this is the only way to define type-specific
operations and to have different representations for different members of
the hierarchy. Your proposal was to render all strings as Wide_Wide_String.
And you tell me about efficiency?

> For instance, I tend to write out the entire name of the conversion between 
> string and unbounded string:
> 
>     Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));

Hideous. What kind of information this mess should convey to the reader?
2/3 of it is noise. My_Object is a string, why Put_Line does not handle it?

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



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

* Re: Is this expected behavior or not
  2013-04-11  7:59                                                                                                                         ` Dmitry A. Kazakov
@ 2013-04-11 11:10                                                                                                                           ` Georg Bauhaus
  2013-04-11 13:49                                                                                                                           ` J-P. Rosen
  2013-04-11 23:02                                                                                                                           ` Randy Brukardt
  2 siblings, 0 replies; 242+ messages in thread
From: Georg Bauhaus @ 2013-04-11 11:10 UTC (permalink / raw)


On 11.04.13 09:59, Dmitry A. Kazakov wrote:
>>> You don't make language design dependent and promoting bad practices.
>> >
>> >If you are starting with a blank page, you're right. If you are building on
>> >30+ years of practice, even "bad practice" has to be taken into account.

> Nonsense. Bad practice is bad. Longer it lasts bigger is the damage.

The consultancy business might be damaged as well when the language
becomes simpler. Or maybe not?




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

* Re: Is this expected behavior or not
  2013-04-11  7:59                                                                                                                         ` Dmitry A. Kazakov
  2013-04-11 11:10                                                                                                                           ` Georg Bauhaus
@ 2013-04-11 13:49                                                                                                                           ` J-P. Rosen
  2013-04-11 15:07                                                                                                                             ` Dmitry A. Kazakov
  2013-04-11 23:02                                                                                                                           ` Randy Brukardt
  2 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-04-11 13:49 UTC (permalink / raw)


Le 11/04/2013 09:59, Dmitry A. Kazakov a �crit :
> type Complex is new Real with record
>    Img : Float;
> end record;
> 
> How is the compiler supposed to inherit "+"?

The problem is not in the language. It is a wrong modelling, since a
complex is not a specialisation of a real.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr



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

* Re: Is this expected behavior or not
  2013-04-11 13:49                                                                                                                           ` J-P. Rosen
@ 2013-04-11 15:07                                                                                                                             ` Dmitry A. Kazakov
  2013-04-12  4:39                                                                                                                               ` J-P. Rosen
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-11 15:07 UTC (permalink / raw)


On Thu, 11 Apr 2013 15:49:03 +0200, J-P. Rosen wrote:

> Le 11/04/2013 09:59, Dmitry A. Kazakov a �crit :
>> type Complex is new Real with record
>>    Img : Float;
>> end record;
>> 
>> How is the compiler supposed to inherit "+"?
> 
> The problem is not in the language. It is a wrong modelling, since a
> complex is not a specialisation of a real.

Type extension is not specialization either.

Specialization in Ada is more or less covered by subtypes. [Type extension
is Cartesian product.]

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



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

* Re: Is this expected behavior or not
  2013-04-11  7:33                                                                                                                                         ` Dmitry A. Kazakov
@ 2013-04-11 22:37                                                                                                                                           ` Randy Brukardt
  2013-04-12  7:47                                                                                                                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-11 22:37 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1q6gm7foi87kr.i2q54bm8sy83.dlg@40tude.net...
...
> In that case there is simply no alternative to multi-methods because n-ary
> operations do not have preferable argument. So what are you going to do
> with this? You ditch operations, literals, slices. A great theory!

Yup, operations that you don't need, and that are dangerous on top of that. 
You continually claim that you need multi-methods without a shred of proof. 
Changing/comparing different representations is something that a program 
should do very rarely, if at all.

                            Randy.





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

* Re: Is this expected behavior or not
  2013-04-11  7:59                                                                                                                         ` Dmitry A. Kazakov
  2013-04-11 11:10                                                                                                                           ` Georg Bauhaus
  2013-04-11 13:49                                                                                                                           ` J-P. Rosen
@ 2013-04-11 23:02                                                                                                                           ` Randy Brukardt
  2013-04-12  8:17                                                                                                                             ` Dmitry A. Kazakov
  2 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-11 23:02 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:1o34nhpfuy6yl$.2orlukd1elr7.dlg@40tude.net...
> On Wed, 10 Apr 2013 17:07:57 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:8bj2k30k7i19.w7ehsldwbf7x.dlg@40tude.net...
>>> On Tue, 9 Apr 2013 18:24:29 -0500, Randy Brukardt wrote:
>> ...
>>>>> Why there should be many?
>>>>
>>>> If you've got operations like "+" or "*", you'll have a lot of 
>>>> functions
>>>> returning objects of the type. That's a bad idea for the reasons I
>>>> mentioned.
>>>
>>> You have + and * of GUI objects? That is weird. Anyway if you have
>>> arithmetic upon a hierarchy how the compiler is supposed to deduce
>>> implementations for derived types?
>>
>> Tagged types and extension is used for more than just GUIs.
>
> Tagged types are useless when arithmetic operations get involved. It does
> not work with present design, because type hierarchies are not handled for
> such operations.
>
>> The compiler shouldn't have trouble with inheriting implementations
>
> type Real is tagged record
>   Value : Float;
> end record;
> function "+" (L, R : Real) return Real;
>
> type Complex is new Real with record
>   Img : Float;
> end record;
>
> How is the compiler supposed to inherit "+"?

Easy, it uses the defined constructor. I explained that in the part of the 
message that you deleted. That's a feature Ada is missing but could easily 
have, especially as we already have something like it for null extensions.

Of course, I don't think Float and Complex have enough in common for this 
sort of derivation to make sense. (The only commonality between float "*" 
and complex "*" is the name.)

...
>>> You don't make language design dependent and promoting bad practices.
>>
>> If you are starting with a blank page, you're right. If you are building 
>> on
>> 30+ years of practice, even "bad practice" has to be taken into account.
>
> Nonsense. Bad practice is bad. Longer it lasts bigger is the damage.

Not nonsense. You can't break existing programs if you expect people to 
upgrade. I've got a million or so lines of Ada code; I can't use a new 
upgraded language on those if they are going to be broken, and I can't 
support a different compiler for every version of code ever written.

If you can detect the "bad practice" at compile-time *and* its rare enough, 
then, and only then, can we consider an incompatibility. Differences at 
run-time are intolerable unless the likelihood of it occurring in practice 
are very small. We've made exceptions to that, but only after many attempts 
to adopt other solutions and a lot of research of existing databases of 
code. (And they're always controversial.)

>> This is one of the reasons that the language you're suggesting really has 
>> to
>> be different than Ada.
>
> We already discussed that. I want to preserve Ada semantics. It is you who
> wants completely change the way string types are used in Ada.

But you're not going to come close to preserving Ada semantics. The model of 
the language is a very important part of that semantics, as it is encoded in 
countless books and articles and tutorials. The gain from abandoning it (and 
we'd have to abandon it to adopt a model like yours) would have to be 
immense.

...
>>>> That isn't very likely to
>>>> happen. The only way to define these conversions would be through a
>>>> Wide_Wide_String intermediate - the net effect is that the conversions
>>>> will be quite expensive and you would never, ever want to use such
>>>> implementations.
>>>
>>> This is exactly the overhead of doing this using the infamous unary plus
>>> operation. I don't understand the point you are trying to make. You 
>>> don't
>>> want to override for custom types, you don't want automatic conversion 
>>> as
>>> too expensive. There is no third way. You want to apply explicit
>>> conversions at all call points? This is exactly the solution you 
>>> declared
>>> inefficient. It not only inefficient, it is extremely error prone and a
>>> major overhead for those unfortunate who have to use the package defined
>>> in such manner. The compiler rejects a program. What you do? Erratically
>>> place unary pluses before all arguments? But that is invisible. Actually 
>>> some
>>> hundred of them are already visible. For each of them the compiler spits
>>> some garbage error messages on you. But the right one you need is not
>>> visible. Were was it declared? Was it declared anywhere? Have fun!
>>
>> You're confusing expensive *implicit* operations with expensive explicit
>> ones. I don't care that an explicit type conversion is expensive -- you
>> wrote it, you meant it, and you can see the consequences -- it's right 
>> there
>> in the source code.
>
> Right, I don't care about performance I care about usability of the
> packages. Only when performance becomes a problem I address that. But I
> never let performance issues to cripple my design.

Fair enough, as I agree in general. But it is important, especially for 
embedded systems, that there is a correlation between the "expense" of the 
construct and how "expensive" it looks. I don't think expensive operations 
should occur automatically, especially if they're a dubious idea to begin 
with.

> But if performance is your concern, you must be the first to go for
> multi-methods, because this is the only way to define type-specific
> operations and to have different representations for different members of
> the hierarchy. Your proposal was to render all strings as 
> Wide_Wide_String.
> And you tell me about efficiency?

It is never a good idea to mix types in a program: String shouldn't be mixed 
with Wide_String, Float with Complex, or Integer with Float. In the rare 
case when you need to do so, you should write an explicit conversion.

There's nothing wrong with storing all strings in unbounded UTF-8, for 
instance, but storing them in a variety of formats will just cause you a 
huge amount of translation overhead. It's not worth it.

The Wide_Wide_Strings are only used for conversions between types and 
literals. (And for slice emulation, although I'm dubious that we need that; 
the operations in Ada.Strings.Fixed are easier to understand and use for 
most things.)

>> For instance, I tend to write out the entire name of the conversion 
>> between
>> string and unbounded string:
>>
>>     Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));
>
> Hideous. What kind of information this mess should convey to the reader?
> 2/3 of it is noise. My_Object is a string, why Put_Line does not handle 
> it?

It's a "string", not a String. Of course it shouldn't handle it. I'd like a 
shorter name for this conversion (preferably a user-defined type 
conversion), but I definitely do not want to get rid of it here.

    Ada.Text_IO.Put_Line (String (My_Object));

seems perfect.

Of course, "General_Text_IO" would take Root_String'Class, so you could 
write what you want with it.

    Ada.General_Text_IO.Put_Line (My_Object);

The internals of the Put_Line operation would be a lot more expensive in 
that case, whether that matters or not depends on the problem (probably not 
for Put_Line).

Anyway, our programming styles are probably 180 degrees apart -- it's not 
surprising that we don't agree on any of this.

                                     Randy.





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

* Re: Is this expected behavior or not
  2013-04-11 15:07                                                                                                                             ` Dmitry A. Kazakov
@ 2013-04-12  4:39                                                                                                                               ` J-P. Rosen
  2013-04-12  8:00                                                                                                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-04-12  4:39 UTC (permalink / raw)


Le 11/04/2013 17:07, Dmitry A. Kazakov a écrit :
>> The problem is not in the language. It is a wrong modelling, since a
>> > complex is not a specialisation of a real.
> Type extension is not specialization either.
> 
> Specialization in Ada is more or less covered by subtypes. [Type extension
> is Cartesian product.]
Well, every proponent of OO will claim that inheritance is about
specialization.

It seems to me that what you call Cartesian product is rather about
composition. And subtypes have nothing to do specialization, at least as
defined in conventional OO.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

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

* Re: Is this expected behavior or not
  2013-04-11 22:37                                                                                                                                           ` Randy Brukardt
@ 2013-04-12  7:47                                                                                                                                             ` Dmitry A. Kazakov
  2013-04-13  0:26                                                                                                                                               ` Randy Brukardt
  2013-04-13  0:35                                                                                                                                               ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-12  7:47 UTC (permalink / raw)


On Thu, 11 Apr 2013 17:37:31 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1q6gm7foi87kr.i2q54bm8sy83.dlg@40tude.net...
> ...
>> In that case there is simply no alternative to multi-methods because n-ary
>> operations do not have preferable argument. So what are you going to do
>> with this? You ditch operations, literals, slices. A great theory!
> 
> Yup, operations that you don't need, and that are dangerous on top of that. 
> You continually claim that you need multi-methods without a shred of proof.

The list of operations required for strings was listed many times:

   function "&" (L, R : Root_String_Type) return Root_String_Type;
   function "=" (L, R : Root_String_Type) return Boolean;
   function "/=" (L, R : Root_String_Type) return Boolean;
   function ">=" (L, R : Root_String_Type) return Boolean;
   function "<=" (L, R : Root_String_Type) return Boolean;
   function ">" (L, R : Root_String_Type) return Boolean;
   function "<" (L, R : Root_String_Type) return Boolean;
   function Overwrite (Source   : in Root_String_Type);
                       Position : in Positive;
                       New_Item : in Root_String_Type)
      return Root_String_Type);

should I continue? It is hundreds of operations, literally. Take into
account a huge set of multi-dispatch operation with containers of strings,
e.g. Character_Set and Character_Mapping. It is thousands of operations you
want to overload? Drop altogether?

> Changing/comparing different representations is something that a program 
> should do very rarely, if at all.

Give "a shred of proof" that Wide_Wide_String must have same representation
as String.

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

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

* Re: Is this expected behavior or not
  2013-04-12  4:39                                                                                                                               ` J-P. Rosen
@ 2013-04-12  8:00                                                                                                                                 ` Dmitry A. Kazakov
  2013-04-12  9:09                                                                                                                                   ` J-P. Rosen
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-12  8:00 UTC (permalink / raw)


On Fri, 12 Apr 2013 06:39:24 +0200, J-P. Rosen wrote:

> Le 11/04/2013 17:07, Dmitry A. Kazakov a écrit :
>>> The problem is not in the language. It is a wrong modelling, since a
>>> > complex is not a specialisation of a real.
>> Type extension is not specialization either.
>> 
>> Specialization in Ada is more or less covered by subtypes. [Type extension
>> is Cartesian product.]

> Well, every proponent of OO will claim that inheritance is about
> specialization.

Specialization constraints the domain set and/or operations, which is not
the case with type extensions. Extensions are popular because they don't
touch the domain set. As a Cartesian product the derived type provides a
mapping to the original domain, you just drop the second member of the
pair: (parent_part, extension_part) -> parent_part. This allows to inherit
many operations, but not factories.

Anyway it is easy to see that specialization breaks some operations too.
The text book case is the circle-ellipse controversy. When you specialize
ellipses to circles you break operations like Resize. Now, how the compiler
is supposed to inherit that?

Ada 95 design was absolutely sound and correct in that respect. I am really
amazed that you and Randy propose to change that to unsafe and semantically
broken behaviour, in order to reduce amount of typing? Is it serious, or
just to counter me?

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


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

* Re: Is this expected behavior or not
  2013-04-11 23:02                                                                                                                           ` Randy Brukardt
@ 2013-04-12  8:17                                                                                                                             ` Dmitry A. Kazakov
  2013-04-12  9:41                                                                                                                               ` Georg Bauhaus
  2013-04-13  0:22                                                                                                                               ` Randy Brukardt
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-12  8:17 UTC (permalink / raw)


On Thu, 11 Apr 2013 18:02:49 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1o34nhpfuy6yl$.2orlukd1elr7.dlg@40tude.net...
>> On Wed, 10 Apr 2013 17:07:57 -0500, Randy Brukardt wrote:
>>
>>> The compiler shouldn't have trouble with inheriting implementations
>>
>> type Real is tagged record
>>   Value : Float;
>> end record;
>> function "+" (L, R : Real) return Real;
>>
>> type Complex is new Real with record
>>   Img : Float;
>> end record;
>>
>> How is the compiler supposed to inherit "+"?
> 
> Easy, it uses the defined constructor.

You must be joking. How the compiler knows how to add complex numbers?

   type Polar_Complex is new Real with record
      Angle : Float;
   end record;

This one too?

> Of course, I don't think Float and Complex have enough in common for this 
> sort of derivation to make sense. (The only commonality between float "*" 
> and complex "*" is the name.)

The commonality is called "field":

http://en.wikipedia.org/wiki/Field_%28mathematics%29

>>>> You don't make language design dependent and promoting bad practices.
>>>
>>> If you are starting with a blank page, you're right. If you are building 
>>> on 30+ years of practice, even "bad practice" has to be taken into account.
>>
>> Nonsense. Bad practice is bad. Longer it lasts bigger is the damage.
> 
> Not nonsense. You can't break existing programs if you expect people to 
> upgrade.

Show me a program that gets broken by introducing untagged classes.

>> But if performance is your concern, you must be the first to go for
>> multi-methods, because this is the only way to define type-specific
>> operations and to have different representations for different members of
>> the hierarchy. Your proposal was to render all strings as 
>> Wide_Wide_String. And you tell me about efficiency?
> 
> It is never a good idea to mix types in a program: String shouldn't be mixed 
> with Wide_String, Float with Complex, or Integer with Float. In the rare 
> case when you need to do so, you should write an explicit conversion.

Ergo, performance is not your concern when it is about the Principle. But
you tried to justify that very principle with performance in first place.

So, we are the to the square one. Why is it never a good idea to use
Ada.Strings.Unbounded.Append [a mixed type operation]?

> There's nothing wrong with storing all strings in unbounded UTF-8, for 
> instance, but storing them in a variety of formats will just cause you a 
> huge amount of translation overhead. It's not worth it.

This is what you proposed. I did to avoid translations through support of
mixed type operations. They do exactly that.

>>> For instance, I tend to write out the entire name of the conversion 
>>> between string and unbounded string:
>>>
>>>     Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));
>>
>> Hideous. What kind of information this mess should convey to the reader?
>> 2/3 of it is noise. My_Object is a string, why Put_Line does not handle 
>> it?
> 
> It's a "string", not a String.

And *semantically* the difference is?

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


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

* Re: Is this expected behavior or not
  2013-04-12  8:00                                                                                                                                 ` Dmitry A. Kazakov
@ 2013-04-12  9:09                                                                                                                                   ` J-P. Rosen
  2013-04-12 17:00                                                                                                                                     ` Jeffrey Carter
  0 siblings, 1 reply; 242+ messages in thread
From: J-P. Rosen @ 2013-04-12  9:09 UTC (permalink / raw)


Le 12/04/2013 10:00, Dmitry A. Kazakov a écrit :
> Ada 95 design was absolutely sound and correct in that respect. I am really
> amazed that you and Randy propose to change that to unsafe and semantically
> broken behaviour, in order to reduce amount of typing? Is it serious, or
> just to counter me?
I agree that the design is right, and I'm not proposing to change anything.

I just said that the commonly accepted meaning of inheritence is
specialization, where the upper level classes are more general and the
lower ones are more specialized. I agree that inheritance has its own
problems - that's why I use it rarely, I prefer composition.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


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

* Re: Is this expected behavior or not
  2013-04-12  8:17                                                                                                                             ` Dmitry A. Kazakov
@ 2013-04-12  9:41                                                                                                                               ` Georg Bauhaus
  2013-04-12 11:46                                                                                                                                 ` Dmitry A. Kazakov
  2013-04-13  0:22                                                                                                                               ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-04-12  9:41 UTC (permalink / raw)


On 12.04.13 10:17, Dmitry A. Kazakov wrote:
>>>> For instance, I tend to write out the entire name of the conversion
>>>> >>>between string and unbounded string:
>>>> >>>
>>>> >>>     Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));
>>> >>
>>> >>Hideous. What kind of information this mess should convey to the reader?
>>> >>2/3 of it is noise. My_Object is a string, why Put_Line does not handle
>>> >>it?
>> >
>> >It's a "string", not a String.
> And*semantically*  the difference is?

The difference is in the meaning that one assigns to "String".
"One" refers to one of two minds performing the assignment:

(a) he who considers a program as per how Ada is defined,
     literally.

(b) he who considers a program in terms of definitions that
     underlie the the definition of Ada, though not literally.



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

* Re: Is this expected behavior or not
  2013-04-12  9:41                                                                                                                               ` Georg Bauhaus
@ 2013-04-12 11:46                                                                                                                                 ` Dmitry A. Kazakov
  2013-04-13 17:38                                                                                                                                   ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-12 11:46 UTC (permalink / raw)


On Fri, 12 Apr 2013 11:41:25 +0200, Georg Bauhaus wrote:

> On 12.04.13 10:17, Dmitry A. Kazakov wrote:
>>>>> For instance, I tend to write out the entire name of the conversion
>>>>> >>>between string and unbounded string:
>>>>> >>>
>>>>> >>>     Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));
>>>> >>
>>>> >>Hideous. What kind of information this mess should convey to the reader?
>>>> >>2/3 of it is noise. My_Object is a string, why Put_Line does not handle
>>>> >>it?
>>> >
>>> >It's a "string", not a String.
>> And*semantically*  the difference is?
> 
> The difference is in the meaning that one assigns to "String".
> "One" refers to one of two minds performing the assignment:
> 
> (a) he who considers a program as per how Ada is defined,
>      literally.
> 
> (b) he who considers a program in terms of definitions that
>      underlie the the definition of Ada, though not literally.

I gather that in your opinion:

1. There is no semantic difference between String and Unbounded_String.

2. Somehow from literal and non-literal considerations it follows that

   Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));

is better/clearer/safer/more efficient than

   Ada.Text_IO.Put_Line (My_Object);

How exactly Put_Line is good with String and bad with Unbounded_String?

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


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

* Re: Is this expected behavior or not
  2013-04-12  9:09                                                                                                                                   ` J-P. Rosen
@ 2013-04-12 17:00                                                                                                                                     ` Jeffrey Carter
  0 siblings, 0 replies; 242+ messages in thread
From: Jeffrey Carter @ 2013-04-12 17:00 UTC (permalink / raw)


On 04/12/2013 02:09 AM, J-P. Rosen wrote:
>
> I just said that the commonly accepted meaning of inheritence is
> specialization, where the upper level classes are more general and the
> lower ones are more specialized. I agree that inheritance has its own
> problems - that's why I use it rarely, I prefer composition.

While it's true that many proponents of type extension claim they're creating 
specialization classifications, starting with general classes and extending them 
to create more specialized ones, it's also demonstrably wrong in most cases: 
It's a rare specialization classification in which the more specialized classes 
need more data than the more general ones. In classifying plane figures, for 
example, the general classes (such as "polygon") clearly need more data in their 
representations than the specialized classes (such as "square").

Type extension starts with abstract classes, and extends them to create more 
concrete ones, a fact that Ada recognizes with its "abstract" reserved word.

-- 
Jeff Carter
"Why, the Mayflower was full of Fireflies, and a few
horseflies, too. The Fireflies were on the upper deck,
and the horseflies were on the Fireflies."
Duck Soup
95

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

* Re: Is this expected behavior or not
  2013-04-12  8:17                                                                                                                             ` Dmitry A. Kazakov
  2013-04-12  9:41                                                                                                                               ` Georg Bauhaus
@ 2013-04-13  0:22                                                                                                                               ` Randy Brukardt
  2013-04-13  6:49                                                                                                                                 ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-13  0:22 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:lhy7cs9p0v0t.jmyir4bofwok.dlg@40tude.net...
> On Thu, 11 Apr 2013 18:02:49 -0500, Randy Brukardt wrote:
...
>> It is never a good idea to mix types in a program: String shouldn't be 
>> mixed
>> with Wide_String, Float with Complex, or Integer with Float. In the rare
>> case when you need to do so, you should write an explicit conversion.
>
> Ergo, performance is not your concern when it is about the Principle. But
> you tried to justify that very principle with performance in first place.
>
> So, we are the to the square one.

Of course. You argue in circles, which makes me go over the same things over 
and over. I'm wasting my time bothering.

> Why is it never a good idea to use
> Ada.Strings.Unbounded.Append [a mixed type operation]?

That's the package that convinced me that mixed operations are never a good 
idea. The intent of the mixed operations was to provide string literals, but 
the effect was that they are available inconsistently and you're at a real 
risk of ambiguity. Moreover, there are cases where you have to convert 
things to String just to do an operation on a value of an Unbounded_String. 
It's just a bad design.

Of course, if you have to use the bad design, then using the operations 
provided in that bad design is unavoidable.

>> There's nothing wrong with storing all strings in unbounded UTF-8, for
>> instance, but storing them in a variety of formats will just cause you a
>> huge amount of translation overhead. It's not worth it.
>
> This is what you proposed. I did to avoid translations through support of
> mixed type operations. They do exactly that.

But you're not eliminating anything. The only way to implement such mixed 
operations is via converting one or the other operands to the most general 
type. Certainly that's required to automatically create such operations, and 
that would have to be the case in order to avoid forcing programmers to 
create thousands of operations for large hierarchies like strings.

In any case, multi-methods don't work given the existing Ada resolution 
rules. You want to fix that with preference rules, but those are a 
non-starter. That's because preference rules give rise to Ripple and 
Beaujolias effects, which are not and will not be tolerated in Ada. (These 
are cases where adding or removing an otherwise unused with or use clause 
can change the meaning of a program.)

Unless you can clearly prove that you have rules that are completely free of 
such effects (which are significant maintenance hazards), the ARG will not 
consider them. (Integrated packages failed in Ada 2012 mainly because we 
couldn't eliminate such effects.)

>>>> For instance, I tend to write out the entire name of the conversion
>>>> between string and unbounded string:
>>>>
>>>>     Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));
>>>
>>> Hideous. What kind of information this mess should convey to the reader?
>>> 2/3 of it is noise. My_Object is a string, why Put_Line does not handle
>>> it?
>>
>> It's a "string", not a String.
>
> And *semantically* the difference is?

Ada is strongly typed; there is currently no such thing as an operation that 
will work on any string type. The origin of this pointless discussion was 
possible ways to fix that, but you are so focused on useless, pie-in-the-sky 
capabilities that we can't sanely explore what we CAN do. (Which is what I 
wanted to do initially.)

                                        Randy.


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

* Re: Is this expected behavior or not
  2013-04-12  7:47                                                                                                                                             ` Dmitry A. Kazakov
@ 2013-04-13  0:26                                                                                                                                               ` Randy Brukardt
  2013-04-13  0:35                                                                                                                                               ` Randy Brukardt
  1 sibling, 0 replies; 242+ messages in thread
From: Randy Brukardt @ 2013-04-13  0:26 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:6ywdes8pgbd8$.alujya2d4454$.dlg@40tude.net...
> On Thu, 11 Apr 2013 17:37:31 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1q6gm7foi87kr.i2q54bm8sy83.dlg@40tude.net...
>> ...
>>> In that case there is simply no alternative to multi-methods because 
>>> n-ary
>>> operations do not have preferable argument. So what are you going to do
>>> with this? You ditch operations, literals, slices. A great theory!
>>
>> Yup, operations that you don't need, and that are dangerous on top of 
>> that.
>> You continually claim that you need multi-methods without a shred of 
>> proof.
>
> The list of operations required for strings was listed many times:
>
>   function "&" (L, R : Root_String_Type) return Root_String_Type;
>   function "=" (L, R : Root_String_Type) return Boolean;
>   function "/=" (L, R : Root_String_Type) return Boolean;
>   function ">=" (L, R : Root_String_Type) return Boolean;
>   function "<=" (L, R : Root_String_Type) return Boolean;
>   function ">" (L, R : Root_String_Type) return Boolean;
>   function "<" (L, R : Root_String_Type) return Boolean;
>   function Overwrite (Source   : in Root_String_Type);
>                       Position : in Positive;
>                       New_Item : in Root_String_Type)
>      return Root_String_Type);
>
> should I continue? It is hundreds of operations, literally. Take into
> account a huge set of multi-dispatch operation with containers of strings,
> e.g. Character_Set and Character_Mapping. It is thousands of operations 
> you
> want to overload? Drop altogether?
>
>> Changing/comparing different representations is something that a program
>> should do very rarely, if at all.
>
> Give "a shred of proof" that Wide_Wide_String must have same 
> representation
> as String.
>
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de 


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

* Re: Is this expected behavior or not
  2013-04-12  7:47                                                                                                                                             ` Dmitry A. Kazakov
  2013-04-13  0:26                                                                                                                                               ` Randy Brukardt
@ 2013-04-13  0:35                                                                                                                                               ` Randy Brukardt
  2013-04-13  7:07                                                                                                                                                 ` Dmitry A. Kazakov
  1 sibling, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-13  0:35 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:6ywdes8pgbd8$.alujya2d4454$.dlg@40tude.net...
> On Thu, 11 Apr 2013 17:37:31 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1q6gm7foi87kr.i2q54bm8sy83.dlg@40tude.net...
>> ...
>>> In that case there is simply no alternative to multi-methods because 
>>> n-ary
>>> operations do not have preferable argument. So what are you going to do
>>> with this? You ditch operations, literals, slices. A great theory!
>>
>> Yup, operations that you don't need, and that are dangerous on top of 
>> that.
>> You continually claim that you need multi-methods without a shred of 
>> proof.
>
> The list of operations required for strings was listed many times:
>
>   function "&" (L, R : Root_String_Type) return Root_String_Type;
>   function "=" (L, R : Root_String_Type) return Boolean;
>   function "/=" (L, R : Root_String_Type) return Boolean;
>   function ">=" (L, R : Root_String_Type) return Boolean;
>   function "<=" (L, R : Root_String_Type) return Boolean;
>   function ">" (L, R : Root_String_Type) return Boolean;
>   function "<" (L, R : Root_String_Type) return Boolean;
>   function Overwrite (Source   : in Root_String_Type);
>                       Position : in Positive;
>                       New_Item : in Root_String_Type)
>      return Root_String_Type);
>
> should I continue? It is hundreds of operations, literally.

Hundreds? You've lost your mind. My rough proposal had 6 (not counting the 
operators). The vast majority of interesting operations should be 
class-wide, not primitive. That includes pretty much everything in the 
Ada.Strings.whatever packages.

>Take into
> account a huge set of multi-dispatch operation with containers of strings,
> e.g. Character_Set and Character_Mapping. It is thousands of operations 
> you
> want to overload? Drop altogether?

I don't see this at all. The element type here is Wide_Wide_Character 
(only), since this is all about Unicode and there's no important reason to 
shorten the representation of singletons. So there's no multi-dispatch and 
all of the existing character sets and mappings can be used as they 
currently are defined.

>> Changing/comparing different representations is something that a program
>> should do very rarely, if at all.
>
> Give "a shred of proof" that Wide_Wide_String must have same 
> representation
> as String.

It doesn't have the same representation; they should never be used together. 
Give me any reason (beyond existing broken interfaces, which we would fix) 
that you should be mixing these two types. Either you're an "ugly American" 
(like me) that thinks Internationalization is mainly about keeping up the 
barriers between people - everyone should use English and forget everything 
else! For us, we'll just use String and we're already happy. For everyone 
else, they'll have to use Wide_Wide_String (or some new string type) 
everywhere. Converting to 8-bit just loses information, and that's a bug in 
many supposely internationalized programs.

                                           Randy.






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

* Re: Is this expected behavior or not
  2013-04-13  0:22                                                                                                                               ` Randy Brukardt
@ 2013-04-13  6:49                                                                                                                                 ` Dmitry A. Kazakov
  2013-04-16  1:41                                                                                                                                   ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-13  6:49 UTC (permalink / raw)


On Fri, 12 Apr 2013 19:22:36 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:lhy7cs9p0v0t.jmyir4bofwok.dlg@40tude.net...
>> On Thu, 11 Apr 2013 18:02:49 -0500, Randy Brukardt wrote:
> ...
>> Why is it never a good idea to use
>> Ada.Strings.Unbounded.Append [a mixed type operation]?
> 
> That's the package that convinced me that mixed operations are never a good 
> idea. The intent of the mixed operations was to provide string literals, but 
> the effect was that they are available inconsistently and you're at a real 
> risk of ambiguity. Moreover, there are cases where you have to convert 
> things to String just to do an operation on a value of an Unbounded_String. 
> It's just a bad design.

And the solution is to remove Append? What would be a "good" design of
Unbounded_String and String such that you never mixed them? Is there any?

You missing the main point that whatever difference Unbounded_String and
String may have, it is not a semantic difference. Both are different
implementations of the same thing. They are mixed right from the start.

>>> There's nothing wrong with storing all strings in unbounded UTF-8, for
>>> instance, but storing them in a variety of formats will just cause you a
>>> huge amount of translation overhead. It's not worth it.
>>
>> This is what you proposed. I did to avoid translations through support of
>> mixed type operations. They do exactly that.
> 
> But you're not eliminating anything. The only way to implement such mixed 
> operations is via converting one or the other operands to the most general 
> type.

Wrong, a multi-method has a body for each combination of parameters.

> In any case, multi-methods don't work given the existing Ada resolution 
> rules. You want to fix that with preference rules, but those are a 
> non-starter.

You cannot know that without even trying to consider these rules or
alternatives to them.

> Unless you can clearly prove that you have rules that are completely free of 
> such effects (which are significant maintenance hazards), the ARG will not 
> consider them.

Sure it will not.

>>>>> For instance, I tend to write out the entire name of the conversion
>>>>> between string and unbounded string:
>>>>>
>>>>>     Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));
>>>>
>>>> Hideous. What kind of information this mess should convey to the reader?
>>>> 2/3 of it is noise. My_Object is a string, why Put_Line does not handle
>>>> it?
>>>
>>> It's a "string", not a String.
>>
>> And *semantically* the difference is?
> 
> Ada is strongly typed; there is currently no such thing as an operation that 
> will work on any string type.

This is why I am asking this question. Where is a semantic difference to
justify the choice to draw a firewall between String and Unbounded_String?

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


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

* Re: Is this expected behavior or not
  2013-04-13  0:35                                                                                                                                               ` Randy Brukardt
@ 2013-04-13  7:07                                                                                                                                                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-13  7:07 UTC (permalink / raw)


On Fri, 12 Apr 2013 19:35:07 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:6ywdes8pgbd8$.alujya2d4454$.dlg@40tude.net...
>> On Thu, 11 Apr 2013 17:37:31 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:1q6gm7foi87kr.i2q54bm8sy83.dlg@40tude.net...
>>> ...
>>>> In that case there is simply no alternative to multi-methods because n-ary
>>>> operations do not have preferable argument. So what are you going to do
>>>> with this? You ditch operations, literals, slices. A great theory!
>>>
>>> Yup, operations that you don't need, and that are dangerous on top of that.
>>> You continually claim that you need multi-methods without a shred of proof.
>>
>> The list of operations required for strings was listed many times:
>>
>>   function "&" (L, R : Root_String_Type) return Root_String_Type;
>>   function "=" (L, R : Root_String_Type) return Boolean;
>>   function "/=" (L, R : Root_String_Type) return Boolean;
>>   function ">=" (L, R : Root_String_Type) return Boolean;
>>   function "<=" (L, R : Root_String_Type) return Boolean;
>>   function ">" (L, R : Root_String_Type) return Boolean;
>>   function "<" (L, R : Root_String_Type) return Boolean;
>>   function Overwrite (Source   : in Root_String_Type);
>>                       Position : in Positive;
>>                       New_Item : in Root_String_Type)
>>      return Root_String_Type);
>>
>> should I continue? It is hundreds of operations, literally.
> 
> Hundreds? You've lost your mind. My rough proposal had 6 (not counting the 
> operators). The vast majority of interesting operations should be 
> class-wide, not primitive. That includes pretty much everything in the 
> Ada.Strings.whatever packages.

Ada 95 already has Wide_Wide_String packages. For fans of explicit
conversions everything is there. Why bothering with new hierarchies? [And
repeating old mistakes?]

>>Take into
>> account a huge set of multi-dispatch operation with containers of strings,
>> e.g. Character_Set and Character_Mapping. It is thousands of operations 
>> you want to overload? Drop altogether?
> 
> I don't see this at all. The element type here is Wide_Wide_Character 
> (only), since this is all about Unicode and there's no important reason to 
> shorten the representation of singletons. So there's no multi-dispatch and 
> all of the existing character sets and mappings can be used as they 
> currently are defined.

Translating String using a Wide_Wide mapping is a mixed operation!

>>> Changing/comparing different representations is something that a program
>>> should do very rarely, if at all.
>>
>> Give "a shred of proof" that Wide_Wide_String must have same 
>> representation as String.
> 
> It doesn't have the same representation; they should never be used together. 
> Give me any reason (beyond existing broken interfaces, which we would fix) 
> that you should be mixing these two types.

The reason is that Wide_Wide_String and String represent exactly same
thing. The motivation to have String is exclusively optimization. Same
applies to Unbounded_String and to encodings.

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


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

* Re: Is this expected behavior or not
  2013-04-12 11:46                                                                                                                                 ` Dmitry A. Kazakov
@ 2013-04-13 17:38                                                                                                                                   ` Georg Bauhaus
  0 siblings, 0 replies; 242+ messages in thread
From: Georg Bauhaus @ 2013-04-13 17:38 UTC (permalink / raw)


On 12.04.13 13:46, Dmitry A. Kazakov wrote:
> On Fri, 12 Apr 2013 11:41:25 +0200, Georg Bauhaus wrote:
>
>> On 12.04.13 10:17, Dmitry A. Kazakov wrote:
>>>>>> For instance, I tend to write out the entire name of the conversion
>>>>>>>>> between string and unbounded string:
>>>>>>>>>
>>>>>>>>>      Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (My_Object));
>>>>>>>
>>>>>>> Hideous. What kind of information this mess should convey to the reader?
>>>>>>> 2/3 of it is noise. My_Object is a string, why Put_Line does not handle
>>>>>>> it?
>>>>>
>>>>> It's a "string", not a String.
>>> And*semantically*  the difference is?
>>
>> The difference is in the meaning that one assigns to "String".
>> "One" refers to one of two minds performing the assignment:
>>
>> (a) he who considers a program as per how Ada is defined,
>>       literally.
>>
>> (b) he who considers a program in terms of definitions that
>>       underlie the the definition of Ada, though not literally.
>
> I gather that in your opinion:
>
> 1. There is no semantic difference between String and Unbounded_String.

The difference is between definitions of semantics (sic), I said.
Semantics is not an absolute. So the meaning of "string" depends
on the assignment of meaning to "string". Here is where there is
a difference. It is an interesting one.

I have not made any value judgments.

One vague hint is a what "string" means is in a certain view of Put.
Another equally rational reference to definitions says that Ada defines
String to be this-and-that, and nothing else. Both are assignments of
meaning to "string". Both are rational. They differ, usefully.

For the sake of an example, let array interfaces be a related issue.
Then, in order to remove all the fog, unveil the statue, just outline,
en detail, for compiler-aware dummies, step by step, how a compiler would
check the user defined array thing for correctness, Ada style,
producing suitable calls of suitably checked user-supplied array operations,
compatible with uses of arrays in places where they can be used today.



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

* Re: Is this expected behavior or not
  2013-04-13  6:49                                                                                                                                 ` Dmitry A. Kazakov
@ 2013-04-16  1:41                                                                                                                                   ` Randy Brukardt
  2013-04-16  8:03                                                                                                                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-16  1:41 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:gj0dksp3fqws$.15ahjs6oqwquj.dlg@40tude.net...
> On Fri, 12 Apr 2013 19:22:36 -0500, Randy Brukardt wrote:
...
> And the solution is to remove Append? What would be a "good" design of
> Unbounded_String and String such that you never mixed them? Is there any?

Not remove Append, but remove the version of Append that mixes two different 
types. The only operations that change types should be explicit conversions 
(possibly user-defined versions of that, using functions).

> You missing the main point that whatever difference Unbounded_String and
> String may have, it is not a semantic difference. Both are different
> implementations of the same thing. They are mixed right from the start.

Representation is an integral part of semantics. I strongly disagree that 
they're representations of the same thing, because that would imply that 
they do exactly the same thing for all operations -- and that's clearly not 
true.

And this is crux of the issue -- we simply do not agree at this fundamental 
level about this topic, and I can't imagine any reason that either of us 
will change our positions here. So we're both wasting our time.

...
>>> This is what you proposed. I did to avoid translations through support 
>>> of
>>> mixed type operations. They do exactly that.
>>
>> But you're not eliminating anything. The only way to implement such mixed
>> operations is via converting one or the other operands to the most 
>> general
>> type.
>
> Wrong, a multi-method has a body for each combination of parameters.
>
>> In any case, multi-methods don't work given the existing Ada resolution
>> rules. You want to fix that with preference rules, but those are a
>> non-starter.
>
> You cannot know that without even trying to consider these rules or
> alternatives to them.

We've tried such rules to solve other problems several times in the past. 
They've almost never worked. And I don't care to try, I see no problem with 
the current state of affairs. It's on you to come up with a worked-out 
solution that you can propose. Otherwise, I'm certain that nothing you want 
to see will happen -- it isn't happening by magic.

                                         Randy.





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

* Re: Is this expected behavior or not
  2013-04-16  1:41                                                                                                                                   ` Randy Brukardt
@ 2013-04-16  8:03                                                                                                                                     ` Dmitry A. Kazakov
  2013-04-16 22:57                                                                                                                                       ` Randy Brukardt
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-16  8:03 UTC (permalink / raw)


On Mon, 15 Apr 2013 20:41:46 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:gj0dksp3fqws$.15ahjs6oqwquj.dlg@40tude.net...
>> On Fri, 12 Apr 2013 19:22:36 -0500, Randy Brukardt wrote:
> ...
>> And the solution is to remove Append? What would be a "good" design of
>> Unbounded_String and String such that you never mixed them? Is there any?
> 
> Not remove Append, but remove the version of Append that mixes two different 
> types.

OK, that is not serious.

> The only operations that change types should be explicit conversions 
> (possibly user-defined versions of that, using functions).

Conversions are mixed type operations per definition:

   function "+" (Value : String) return Unbounded_String;

is mixed, and additionally a multi-method if String and Unbounded_String in
the same hierarchy with "+" defined there.

>> You missing the main point that whatever difference Unbounded_String and
>> String may have, it is not a semantic difference. Both are different
>> implementations of the same thing. They are mixed right from the start.
> 
> Representation is an integral part of semantics.

I don't understand why you are using Ada then. There are lots of great
languages which pursue the principle that representation is semantics,
beginning with C.

> I strongly disagree that 
> they're representations of the same thing, because that would imply that 
> they do exactly the same thing for all operations -- and that's clearly not 
> true.

That is certainly true. All operations of these types deal with exactly
same thing called "string." Whatever difference existed is motivated solely
by implementation reasons, e.g. by memory management issues. These are
irrelevant to what string is: a sequence of code points with operations
like (), &, <, <=, Put_Line etc.

> I'm certain that nothing you want 
> to see will happen -- it isn't happening by magic.

Clearly so, when even separation of implementation and interface is no more
considered Ada's design principle.

I have no illusions. The trend is obvious when looking at Ada 2005 and
2012.

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



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

* Re: Is this expected behavior or not
  2013-04-16  8:03                                                                                                                                     ` Dmitry A. Kazakov
@ 2013-04-16 22:57                                                                                                                                       ` Randy Brukardt
  2013-04-17  7:18                                                                                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-16 22:57 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:144bgnv8rdks7$.1o76z1eh196ks$.dlg@40tude.net...
> On Mon, 15 Apr 2013 20:41:46 -0500, Randy Brukardt wrote:
...
>>> You missing the main point that whatever difference Unbounded_String and
>>> String may have, it is not a semantic difference. Both are different
>>> implementations of the same thing. They are mixed right from the start.
>>
>> Representation is an integral part of semantics.
>
> I don't understand why you are using Ada then. There are lots of great
> languages which pursue the principle that representation is semantics,
> beginning with C.

Representation is not semantics -- it's *part* of semantics -- there are 
other components to semantics as well, which languages like C ignore. But 
you're ignoring the part of semantics that is associated with 
representation, and that's just as bad.

One type for one purpose. If you think you need different representations 
for a type, you're clearly mixing purposes and that's bad.

Anyway, I use Ada because it forces me to write precisely and it complains 
about any abuse of types. And because it has the most sensible syntax of any 
language that I've been seriously exposed to. And most of all, because it 
automatically includes lots of dynamic checks to prevent mistakes from 
spreading (I hate debugging). The latter two are the most important, and 
they are only tangentially involved with types.

                                    Randy.





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

* Re: Is this expected behavior or not
  2013-04-16 22:57                                                                                                                                       ` Randy Brukardt
@ 2013-04-17  7:18                                                                                                                                         ` Dmitry A. Kazakov
  2013-04-17  9:23                                                                                                                                           ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-17  7:18 UTC (permalink / raw)


On Tue, 16 Apr 2013 17:57:20 -0500, Randy Brukardt wrote:

> One type for one purpose. If you think you need different representations 
> for a type, you're clearly mixing purposes and that's bad.

This is deeply wrong. In software engineering we have functional and
non-functional requirements to deal with the situation that no computing
system can adequately reflect the problem space. Semantics is functional.
Representation is non-functional and to large extent arbitrary. This is why
same things can and must be implemented differently using different
representations and different algorithms for its operations within the same
system. Which is why Ada has infinite number of string types (counting
bounded strings) which serve single purpose of dealing with sequences of
characters.

If you think otherwise your proposal should be a universal string type
suitable for all systems from tiny embedded targets, for all memory
management strategies, for all types of encoding, for all character sets.

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



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

* Re: Is this expected behavior or not
  2013-04-17  7:18                                                                                                                                         ` Dmitry A. Kazakov
@ 2013-04-17  9:23                                                                                                                                           ` Georg Bauhaus
  2013-04-17  9:57                                                                                                                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-04-17  9:23 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote:
>.
> Representation is non-functional and to large extent arbitrary. 

The functional specification may refer to
TIME and SPACE in essential ways, giving
precise declarations of what is not to be
exceeded. Within the formal limits and 
possibilities of the system given, this requires
judicious use of, well, what, if the programmer
must not declare some sort of representations?
How does a type cover essential behavioral
aspects of time and space if representation
may not be part of the type system?

If the Ada type system cannot express
time and space, I'll still consider them
functional requirements. And I'd much rather
want the types to state them, rather than
hands waving stories about implementations.



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

* Re: Is this expected behavior or not
  2013-04-17  9:23                                                                                                                                           ` Georg Bauhaus
@ 2013-04-17  9:57                                                                                                                                             ` Dmitry A. Kazakov
  2013-04-17 19:38                                                                                                                                               ` Georg Bauhaus
  0 siblings, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-17  9:57 UTC (permalink / raw)


On 17 Apr 2013 09:23:26 GMT, Georg Bauhaus wrote:

> How does a type cover essential behavioral
> aspects of time and space if representation
> may not be part of the type system?

Representation clauses for task types, memory layout of the TCB? (:-))

> If the Ada type system cannot express
> time and space, I'll still consider them
> functional requirements.

And this should justify conflation of a representation with the type
semantics... surely.

> And I'd much rather
> want the types to state them, rather than
> hands waving stories about implementations.

Excellent, A.4.5:

package Ada.Strings.Unbounded is
   type Unbounded_String is private;

This sort of thing of representation declaration?

It is always interesting to observe the ends people are ready to go
defending undefendable...

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



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

* Re: Is this expected behavior or not
  2013-04-17  9:57                                                                                                                                             ` Dmitry A. Kazakov
@ 2013-04-17 19:38                                                                                                                                               ` Georg Bauhaus
  2013-04-18 11:52                                                                                                                                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Georg Bauhaus @ 2013-04-17 19:38 UTC (permalink / raw)


On 17.04.13 11:57, Dmitry A. Kazakov wrote:

>> If the Ada type system cannot express
>> time and space, I'll still consider them
>> functional requirements.
>
> And this should justify conflation of a representation with the type
> semantics... surely.

Representation is functional, like it or not, and it is meaningful,
therefore it is semantically important.

Nothing is conflated here because semantics is assignment of meaning,
not just types-whatever. Provide a different hook for stating
functionally important representation and programmers might use it.
For example, for this: "Make X a Θ(1) data structure of equally shaped
objects of the same subtype, of a certain finite length, indexed by
certain discrete values, components well aligned."

For sure, type semantics, if that restriction should so easily mean a
thing in a real-world programming language, isn't semantics.  The
meaning of an Ada program, for example, is determined by the
implementation (RM 1.1.3). Period. That's also true in other
languages.

But I can be certain to get the Θ(1) thing mentioned above by making
the necessary declarations in Ada, because of the meaning it assigns
to "array".

String is a good example. String is an array, and nothing else.

The existence of RM A.4.({4,5}) is of no consequence. To hell with it.

The existence of RM 3.6 is essential, because of array semantics.

(And I don't care much about string literals because many are read
from external sources during start-up. YMMV.)

The only important type for text processing for me is the universal
type to be used for defining text character types, because ranges of
characters match notions relating to text just like ranges of whole
numbers match notions relating to mathematical integers.  There are
excellent libraries full of text processing operations. If they give
rise to universally good operators, excellent! If they need to involve
representation, then so be it. I live in and off dirt, not
mathematical purity, so long as the latter offers no way to denote
functional requirements such as representing objects.




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

* Re: Is this expected behavior or not
  2013-04-17 19:38                                                                                                                                               ` Georg Bauhaus
@ 2013-04-18 11:52                                                                                                                                                 ` Dmitry A. Kazakov
  2013-04-19  2:16                                                                                                                                                   ` Randy Brukardt
  2013-04-19  9:07                                                                                                                                                   ` Georg Bauhaus
  0 siblings, 2 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-18 11:52 UTC (permalink / raw)


On Wed, 17 Apr 2013 21:38:28 +0200, Georg Bauhaus wrote:

> On 17.04.13 11:57, Dmitry A. Kazakov wrote:
> 
>>> If the Ada type system cannot express
>>> time and space, I'll still consider them
>>> functional requirements.
>>
>> And this should justify conflation of a representation with the type
>> semantics... surely.
> 
> Representation is functional,

You should feel obliged to write an AI to disband ARM 7.3.

> Nothing is conflated here because semantics is assignment of meaning,

http://en.wikipedia.org/wiki/Semantics

> String is a good example. String is an array, and nothing else.

Wrong. String has an array interface. In fact it has at least two array
interfaces one of character/code points, another of encoding units.
Operations like Find can be considered a third array interface. In many
languages strings can be indexed by strings.

> The existence of RM A.4.({4,5}) is of no consequence. To hell with it.

In that case show us a way to create unbounded arrays with representation
guts inside out.

Your concept simply does not hold. There are simple indisputable facts:

1. The representation of string object is irrelevant to what string is.

2. It is impossible to have one implementation suitable for all string
objects and all application domains that use strings, e.g. DNA sequencing,
pattern matching, text processing, compiler construction etc.

> The existence of RM 3.6 is essential, because of array semantics.

Array semantics? What's that? You claimed that semantics is representation.

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



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

* Re: Is this expected behavior or not
  2013-04-18 11:52                                                                                                                                                 ` Dmitry A. Kazakov
@ 2013-04-19  2:16                                                                                                                                                   ` Randy Brukardt
  2013-04-19  7:39                                                                                                                                                     ` Dmitry A. Kazakov
  2013-04-19  9:07                                                                                                                                                   ` Georg Bauhaus
  1 sibling, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-19  2:16 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:qtagj9gwjjxn$.ljj8purwznkr.dlg@40tude.net...
...
> Your concept simply does not hold. There are simple indisputable facts:
>
> 1. The representation of string object is irrelevant to what string is.

This is clearly false, so it's pretty clear why you end up with bizarre 
conclusions.

Specifically, the number of characters that a string object can hold (and 
whether that number can change, and by how much) is *indisputably* a 
critical part of string object semantics. This is so tightly interwined by 
the underlying representation (when you chose one, you pretty much chose the 
other) that practically it is inseparable.

It's certainly true that you can have an abstract string interface that 
doesn't expose the representation -- that's the idea behind my 
Root_String'Class proposal -- and that's useful in a limited set of 
circumstances (mostly in read-only situations, which is the majority of 
string operations anyway). But it does not describe the complete semantics 
of a string object, nor could it.

> 2. It is impossible to have one implementation suitable for all string
> objects and all application domains that use strings, e.g. DNA sequencing,
> pattern matching, text processing, compiler construction etc.

Of course. So what? That's why we want a variety of string types for 
different jobs. That gives no reason why anyone should be mixing them! What 
do you get when you concatenate a DNA sequence and an Ada identifier? A bug! 
:-)

                                    Randy.





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

* Re: Is this expected behavior or not
  2013-04-19  2:16                                                                                                                                                   ` Randy Brukardt
@ 2013-04-19  7:39                                                                                                                                                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-19  7:39 UTC (permalink / raw)


On Thu, 18 Apr 2013 21:16:58 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:qtagj9gwjjxn$.ljj8purwznkr.dlg@40tude.net...
> ...
>> Your concept simply does not hold. There are simple indisputable facts:
>>
>> 1. The representation of string object is irrelevant to what string is.
> 
> This is clearly false, so it's pretty clear why you end up with bizarre 
> conclusions.

http://en.wikipedia.org/wiki/String_%28computer_science%29

> Specifically, the number of characters that a string object can hold (and 
> whether that number can change, and by how much) is *indisputably* a 
> critical part of string object semantics.

Confusing semantics of objects with semantics of values they hold?

Anyway your argument is evidently bogus as follows from:

   X : constant Unbounded_String := whatever;

Is X a string object? Can you change the number of characters in there?
Does it have a different representation? Do you care if it does?

> It's certainly true that you can have an abstract string interface that 
> doesn't expose the representation -- that's the idea behind my 
> Root_String'Class proposal -- and that's useful in a limited set of 
> circumstances (mostly in read-only situations, which is the majority of 
> string operations anyway). But it does not describe the complete semantics 
> of a string object, nor could it.

"Complete semantics" (whatever it means) /= string semantics.

>> 2. It is impossible to have one implementation suitable for all string
>> objects and all application domains that use strings, e.g. DNA sequencing,
>> pattern matching, text processing, compiler construction etc.
> 
> Of course. So what?

Multiple string types => have to mix them

[in the contexts where only string semantics is relevant]

> That's why we want a variety of string types for 
> different jobs. That gives no reason why anyone should be mixing them!

It is the reason, because otherwise you must show that no program can  do
more than one job ever.

> What 
> do you get when you concatenate a DNA sequence and an Ada identifier?

Meaningless question as there is no string type of Ada identifiers. Are you
arguing that Ada identifiers require a special representation? A different
representation from C identifiers? Are you saying that some string types
shall not be mixed? Remember our discussion about cloning types? This has
nothing to do with representations:

   type Ada_Identifier is new String;
   type C_Identifier is new String;

The representation is same. Types are different. String semantics is same.
Semantics relevant to compiler/parser construction could be same or
different depending on the circumstances.

You cannot determine this at the language level. You shall leave that to
the programmer. It is his decision only whether types he designs to be
mixed or not.

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



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

* Re: Is this expected behavior or not
  2013-04-18 11:52                                                                                                                                                 ` Dmitry A. Kazakov
  2013-04-19  2:16                                                                                                                                                   ` Randy Brukardt
@ 2013-04-19  9:07                                                                                                                                                   ` Georg Bauhaus
  2013-04-19  9:11                                                                                                                                                     ` Georg Bauhaus
  2013-04-19 12:09                                                                                                                                                     ` Dmitry A. Kazakov
  1 sibling, 2 replies; 242+ messages in thread
From: Georg Bauhaus @ 2013-04-19  9:07 UTC (permalink / raw)


On 18.04.13 13:52, Dmitry A. Kazakov wrote:
> On Wed, 17 Apr 2013 21:38:28 +0200, Georg Bauhaus wrote:
>
>> On 17.04.13 11:57, Dmitry A. Kazakov wrote:
>>
>>>> If the Ada type system cannot express
>>>> time and space, I'll still consider them
>>>> functional requirements.
>>>
>>> And this should justify conflation of a representation with the type
>>> semantics... surely.
>>
>> Representation is functional,
>
> You should feel obliged to write an AI to disband ARM 7.3.

Semantics is not restricted to private types. Neither is any of the
perspectives on semantics demonstrably more important, so much more
important that other perspective do not matter to programmers
(or language designers, I'd think).

>> Nothing is conflated here because semantics is assignment of meaning,
>
> http://en.wikipedia.org/wiki/Semantics

Yes, you might want to read it once more:

  "Semantics (from Ancient Greek: σημαντικός sēmantikós) is the study of
    meaning. It focuses on the relation between signifiers, like words,
    phrases, signs, and symbols, and what they stand for, their denotation."

Thus, a functional requirement can be expressed as

   for A'Component_Size use 24;  -- needed for CRM 114

and that which this declaration stands for is a consequence of Ada.
It is much less a consequence of what a delighted mind might otherwise
read into it, however spirited that other meaning may be.
Semantics is not restricted to private types. Some things are
language defined.

>> String is a good example. String is an array, and nothing else.
>
> Wrong. String has an array interface.

No, right. String has the "interface" of array. Period.
Some intellectual type that some people may want to call
"string" has some other properties. I may want to call
this type Egg. Clearly, it is not a string then, right?
Conversely, not everything that is called "string" is well
defined because it someone calls it "string".

> Operations like Find can be considered a third array interface.

Confusion starts precisely from considering the mix of language
defined semantics and used defined types.

Go ahead. Tell us how a compiler will check the consistency
of used defined array types with built-in arrays in all required
places in Ada programs; then, suggesting a different array
facility for Ada might be more convincing.

> In many
> languages strings can be indexed by strings.

Show me one, I'm curios. Hashing is not indexing by strings, because
hashing means computing a non-string that is to be used as the index
value. The same is true for computing a position number for a find.
  
>> The existence of RM A.4.({4,5}) is of no consequence. To hell with it.
>
> In that case show us a way to create unbounded arrays with representation
> guts inside out.

Ada does not have unbounded arrays and is not going to have them,
I dare say. Instead, I suggest that you focus on creating/stealing types
useful for text processing, and make them very different---unless you
can finally produce a user-definable array facility 100% compatible
with the known Ada array facility. Their only relation to current String
(the current array) should be subprograms for conversion. How about
that?


> Your concept simply does not hold. There are simple indisputable facts:
>
> 1. The representation of string object is irrelevant to what string is.

Again, an occurrence of, and stipulation of truth in, the auxiliary
verb "is", without offering the necessary definitions of (a) its meaning,
(b) a proof of concept.

> 2. It is impossible to have one implementation suitable for all string
> objects and all application domains that use strings, e.g. DNA sequencing,
> pattern matching, text processing, compiler construction etc.

Yes, the impossible string. And equally unlikely, there will be
"whatever-way-generic" types that have substitutable sets of operations
suitable for all "string processing". (Should the Find operation be
required to be stateful so that it can be used in a lazy iteration
scheme? Why? Why not?)

>> The existence of RM 3.6 is essential, because of array semantics.
>
> Array semantics? What's that?

When I declare an array type, RM 3.6 instructs about the meaning.

> You claimed that semantics is representation.

Again, a nice occurrence of a rhetorical classic. I said, instead:

  "Representation ... is meaningful, therefore it is semantically important."
  "semantics is assignment of meaning,"

http://en.wikipedia.org/wiki/Semantics




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

* Re: Is this expected behavior or not
  2013-04-19  9:07                                                                                                                                                   ` Georg Bauhaus
@ 2013-04-19  9:11                                                                                                                                                     ` Georg Bauhaus
  2013-04-19 12:09                                                                                                                                                     ` Dmitry A. Kazakov
  1 sibling, 0 replies; 242+ messages in thread
From: Georg Bauhaus @ 2013-04-19  9:11 UTC (permalink / raw)


On 19.04.13 11:07, Georg Bauhaus wrote:
>
> Confusion starts precisely from considering the mix of language
> defined semantics and used defined types.

I'll correct a typo in the sentence because it (the sentence) is
important to me.

Confusion starts precisely from considering the mix of language
defined semantics and user defined types.

> Go ahead. Tell us how a compiler will check the consistency
> of user defined array types with built-in arrays in all required
> places in Ada programs; then, suggesting a different array
> facility for Ada might be more convincing.




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

* Re: Is this expected behavior or not
  2013-04-19  9:07                                                                                                                                                   ` Georg Bauhaus
  2013-04-19  9:11                                                                                                                                                     ` Georg Bauhaus
@ 2013-04-19 12:09                                                                                                                                                     ` Dmitry A. Kazakov
  2013-04-19 22:14                                                                                                                                                       ` Randy Brukardt
  1 sibling, 1 reply; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-19 12:09 UTC (permalink / raw)


On Fri, 19 Apr 2013 11:07:05 +0200, Georg Bauhaus wrote:

> On 18.04.13 13:52, Dmitry A. Kazakov wrote:
>> On Wed, 17 Apr 2013 21:38:28 +0200, Georg Bauhaus wrote:
>>
>>> On 17.04.13 11:57, Dmitry A. Kazakov wrote:
>>>
>>>>> If the Ada type system cannot express
>>>>> time and space, I'll still consider them
>>>>> functional requirements.
>>>>
>>>> And this should justify conflation of a representation with the type
>>>> semantics... surely.
>>>
>>> Representation is functional,
>>
>> You should feel obliged to write an AI to disband ARM 7.3.
> 
> Semantics is not restricted to private types.

Private types have no semantics?

Hint: language semantics /= program semantics

>>> Nothing is conflated here because semantics is assignment of meaning,
>>
>> http://en.wikipedia.org/wiki/Semantics
> 
> Yes, you might want to read it once more:
> 
>   "Semantics (from Ancient Greek: σημαντικός sēmantikós) is the study of
>     meaning. It focuses on the relation between signifiers, like words,
>     phrases, signs, and symbols, and what they stand for, their denotation."

Semantics is not assignment of meaning. "Assignment of meaning" is an act
of translation, understanding, cognition.

>>> String is a good example. String is an array, and nothing else.
>>
>> Wrong. String has an array interface.
> 
> No, right. String has the "interface" of array. Period.

has /= is

>> Operations like Find can be considered a third array interface.
> 
> Confusion starts precisely from considering the mix of language
> defined semantics and used defined types.

Confusion of what with what?

> Go ahead. Tell us how a compiler will check the consistency
> of used defined array types with built-in arrays in all required
> places in Ada programs;

What is consistency of types and why the compiler must check it. Ada RM is
silent about that. Anyway, normally, in formal systems or semi-formal ones
like Ada programming language is, consistency (using standard meaning of
this word) is guaranteed per construction of corresponding entities.

Though I don't see how all this is related to array interfaces, built-in or
not arrays, string types etc. There are certain requirements any
implementation of array interface has to obey. Those are customary written
in the RM under "implementation requirements" clauses.

>> In many languages strings can be indexed by strings.
> 
> Show me one,

http://en.wikipedia.org/wiki/Associative_array

>>> The existence of RM A.4.({4,5}) is of no consequence. To hell with it.
>>
>> In that case show us a way to create unbounded arrays with representation
>> guts inside out.
> 
> Ada does not have unbounded arrays and is not going to have them,

Thus either your statement that string is an array is wrong or else
Unbounded_Array is not string. The choice is yours.

> I dare say. Instead, I suggest that you focus on creating/stealing types
> useful for text processing, and make them very different---unless you
> can finally produce a user-definable array facility 100% compatible
> with the known Ada array facility. Their only relation to current String
> (the current array) should be subprograms for conversion. How about
> that?

No idea. The question was how to implement unbounded strings exposing the
representation. Do that first. Then the second question would be why on
earth one should expose such a representation. The third question is why
the RM should mandate this representation prohibiting other
representations.

>> Your concept simply does not hold. There are simple indisputable facts:
>>
>> 1. The representation of string object is irrelevant to what string is.
> 
> Again, an occurrence of, and stipulation of truth in, the auxiliary
> verb "is", without offering the necessary definitions of (a) its meaning,
> (b) a proof of concept.

Please, explain how representation aspects are relevant to the notion of
strings in programming. That requires, in particular, a proof that all
programming languages that deploy strings necessarily use same
representation of.

>> 2. It is impossible to have one implementation suitable for all string
>> objects and all application domains that use strings, e.g. DNA sequencing,
>> pattern matching, text processing, compiler construction etc.
> 
> Yes, the impossible string.

q.e.d.

>>> The existence of RM 3.6 is essential, because of array semantics.
>>
>> Array semantics? What's that?
> 
> When I declare an array type, RM 3.6 instructs about the meaning.

Which is? You are confusing language semantics with program semantics.

>> You claimed that semantics is representation.
> 
> Again, a nice occurrence of a rhetorical classic. I said, instead:
> 
>   "Representation ... is meaningful, therefore it is semantically important."
>   "semantics is assignment of meaning,"

So representation is not semantics/meaning, at least to the programmer, of
course, not to the hardware running the program, not to the artist using
code printouts as tapestry patterns etc.

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



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

* Re: Is this expected behavior or not
  2013-04-19 12:09                                                                                                                                                     ` Dmitry A. Kazakov
@ 2013-04-19 22:14                                                                                                                                                       ` Randy Brukardt
  2013-04-20  6:39                                                                                                                                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 242+ messages in thread
From: Randy Brukardt @ 2013-04-19 22:14 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:84dn4lxu5j$.1mi40bvj8e8tc$.dlg@40tude.net...
> On Fri, 19 Apr 2013 11:07:05 +0200, Georg Bauhaus wrote:
...
>>   "Representation ... is meaningful, therefore it is semantically 
>> important."
>>   "semantics is assignment of meaning,"
>
> So representation is not semantics/meaning, at least to the programmer, of
> course, not to the hardware running the program, not to the artist using
> code printouts as tapestry patterns etc.

Ah, now we get to the root of the problem. We're talking about Ada 
programming language design here, so when I talk about "semantics", I'm 
talking about the semantics of the Ada programming language, as specified in 
the Ada standard. I'm not talking about whatever ideas - quite possibly 
incorrect - that the programmer might have about how their program works. 
Those could be anything at all, and much like theology, cannot be usefully 
reasoned about. I've had plenty of misconceptions about Ada myself, even 
now. Not much point in discussing programmers views (beyond what we would 
LIKE them to be) when discussing detailed semantics.

When you ask:

> Confusing semantics of objects with semantics of values they hold?

you're demonstrating *your* confusion. We're talking about string objects 
here. And Ada doesn't have composite values; there are only objects. There 
are no semantics of composite values, so it's impossible to confuse them 
with something that does exist.

You then go on to say that the existence of different types requires mixing 
and then at the same time says that different types surely must be kept 
separate even if the representation is the same. You're essentially arguing 
both sides of this argument at the same time.

One last time: I agree there is value to "generic" (English, not Ada 
meaning) operations for types. I don't consider such operations "mixing". 
And occassionally you'll need to explicitly convert one type to another. But 
that's it.

                                  Randy.







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

* Re: Is this expected behavior or not
  2013-04-19 22:14                                                                                                                                                       ` Randy Brukardt
@ 2013-04-20  6:39                                                                                                                                                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 242+ messages in thread
From: Dmitry A. Kazakov @ 2013-04-20  6:39 UTC (permalink / raw)


On Fri, 19 Apr 2013 17:14:52 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:84dn4lxu5j$.1mi40bvj8e8tc$.dlg@40tude.net...
>> On Fri, 19 Apr 2013 11:07:05 +0200, Georg Bauhaus wrote:
> ...
>>>   "Representation ... is meaningful, therefore it is semantically 
>>> important."
>>>   "semantics is assignment of meaning,"
>>
>> So representation is not semantics/meaning, at least to the programmer, of
>> course, not to the hardware running the program, not to the artist using
>> code printouts as tapestry patterns etc.
> 
> Ah, now we get to the root of the problem. We're talking about Ada 
> programming language design here, so when I talk about "semantics", I'm 
> talking about the semantics of the Ada programming language, as specified in 
> the Ada standard.

So you are talking a tautology that the machine executes the program
according to the language standard. Which is completely irrelevant to the
issue, which is how programs are designed and what is required from the
language side to support this activity.

>> Confusing semantics of objects with semantics of values they hold?
> 
> you're demonstrating *your* confusion. We're talking about string objects 
> here. And Ada doesn't have composite values; there are only objects.

Yes, this is the core of your confusion. You conflate language semantics
with program semantics. String is a problem space entity. The language may
have some built-in types or means in order to model strings. These types
are strings so long they model what programmers call "string." No longer.
If for whatever reason there must be more than one type to model the same
thing [string] these types must be mixed.

> You then go on to say that the existence of different types requires mixing 
> and then at the same time says that different types surely must be kept 
> separate even if the representation is the same. You're essentially arguing 
> both sides of this argument at the same time.

Not at all. I say that the choice depends on the problem space. Types are
used to model things. When modeled things are unrelated so must be the
types. When modeled things are related then types must be mixed.
Representation is irrelevant it is a vehicle to achieve the goal, an
implementation detail.

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



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

end of thread, other threads:[~2013-04-20  6:39 UTC | newest]

Thread overview: 242+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-11 19:42 Is this expected behavior or not Anh Vo
2013-03-11 20:01 ` Robert A Duff
2013-03-11 20:41   ` Shark8
2013-03-12  9:27     ` Dmitry A. Kazakov
2013-03-12 17:19       ` Robert A Duff
2013-03-12 17:42         ` Dmitry A. Kazakov
2013-03-12 18:04           ` Georg Bauhaus
2013-03-12 18:21             ` Dmitry A. Kazakov
2013-03-12 22:23               ` Georg Bauhaus
2013-03-13  8:49                 ` Dmitry A. Kazakov
2013-03-13  9:45                   ` J-P. Rosen
2013-03-13 13:31                     ` Dmitry A. Kazakov
2013-03-13 14:34                       ` Georg Bauhaus
2013-03-13 15:51                         ` Dmitry A. Kazakov
2013-03-13 16:56                           ` Jeffrey Carter
2013-03-13 17:09                             ` Shark8
2013-03-13 17:32                           ` Georg Bauhaus
2013-03-13 19:28                             ` Dmitry A. Kazakov
2013-03-13 21:01                               ` Randy Brukardt
2013-03-13 21:18                                 ` Dmitry A. Kazakov
2013-03-14 21:51                                   ` Randy Brukardt
2013-03-15  1:10                                     ` Adam Beneschan
2013-03-15 21:22                                       ` Randy Brukardt
2013-03-15  9:20                                     ` Dmitry A. Kazakov
2013-03-15 21:43                                       ` Randy Brukardt
2013-03-16  7:56                                         ` Dmitry A. Kazakov
2013-03-18 22:52                                           ` Randy Brukardt
2013-03-19 10:32                                             ` Dmitry A. Kazakov
2013-03-13 21:37                               ` Georg Bauhaus
2013-03-14 11:18                                 ` Dmitry A. Kazakov
2013-03-14 12:37                                   ` Georg Bauhaus
2013-03-14 14:26                                     ` Dmitry A. Kazakov
2013-03-14 14:57                                       ` Georg Bauhaus
2013-03-14 15:51                                         ` Anh Vo
2013-03-14 16:21                                       ` J-P. Rosen
2013-03-14 17:29                                         ` Dmitry A. Kazakov
2013-03-14 18:16                                           ` Georg Bauhaus
2013-03-15  9:33                                             ` Dmitry A. Kazakov
2013-03-15 10:05                                               ` Georg Bauhaus
2013-03-15 11:15                                                 ` Dmitry A. Kazakov
2013-03-14 22:12                                           ` Randy Brukardt
2013-03-15  9:46                                             ` Dmitry A. Kazakov
     [not found]                                             ` <ewe0v3ck1xdo$.e8rtuof27ke6$.dlg@40tude.net >
2013-03-15 21:17                                               ` Randy Brukardt
2013-03-16  7:51                                                 ` Dmitry A. Kazakov
2013-03-16  9:30                                                   ` Georg Bauhaus
2013-03-16 10:27                                                     ` Dmitry A. Kazakov
2013-03-16 11:37                                                       ` Georg Bauhaus
2013-03-16 13:04                                                         ` Dmitry A. Kazakov
2013-03-16 16:10                                                           ` Georg Bauhaus
2013-03-16 17:47                                                             ` Dmitry A. Kazakov
2013-03-18 22:36                                                   ` Randy Brukardt
2013-03-19 10:14                                                     ` Dmitry A. Kazakov
2013-03-19 14:23                                                       ` Georg Bauhaus
2013-03-19 15:13                                                         ` Dmitry A. Kazakov
2013-03-19 16:52                                                           ` Georg Bauhaus
2013-03-19 17:31                                                             ` Dmitry A. Kazakov
2013-03-19 20:07                                                               ` J-P. Rosen
2013-03-19 20:45                                                                 ` Dmitry A. Kazakov
2013-03-19 21:59                                                                   ` J-P. Rosen
2013-03-20 10:04                                                                     ` Dmitry A. Kazakov
2013-03-20 11:01                                                                       ` J-P. Rosen
2013-03-20 13:21                                                                         ` Dmitry A. Kazakov
2013-03-20 23:31                                                                           ` Randy Brukardt
2013-03-21  9:08                                                                             ` Dmitry A. Kazakov
2013-03-22 10:23                                                                           ` J-P. Rosen
2013-03-22 14:54                                                                             ` Dmitry A. Kazakov
2013-03-22 22:18                                                                               ` J-P. Rosen
2013-03-22 23:05                                                                                 ` Shark8
2013-03-23  8:32                                                                                   ` Dmitry A. Kazakov
2013-03-23  8:14                                                                                 ` Dmitry A. Kazakov
2013-03-23  9:02                                                                                   ` J-P. Rosen
2013-03-23 10:19                                                                                     ` Dmitry A. Kazakov
2013-03-23 21:53                                                                                       ` J-P. Rosen
2013-03-24  8:17                                                                                         ` Dmitry A. Kazakov
2013-03-24  8:27                                                                                           ` J-P. Rosen
2013-03-24 13:01                                                                                             ` AdaMagica
2013-03-25  8:32                                                                                             ` Dmitry A. Kazakov
2013-03-25  9:19                                                                                               ` Georg Bauhaus
2013-03-25 10:08                                                                                                 ` Dmitry A. Kazakov
2013-03-19 21:37                                                       ` Randy Brukardt
2013-03-20  8:48                                                         ` Dmitry A. Kazakov
2013-03-14 16:22                                       ` Shark8
2013-03-14 17:08                                         ` Dmitry A. Kazakov
2013-03-13 22:34                               ` Robert A Duff
2013-03-14  9:09                                 ` Dmitry A. Kazakov
2013-03-14  9:27                                   ` Georg Bauhaus
2013-03-13 17:05                         ` Shark8
2013-03-13 17:45                           ` Simon Wright
2013-03-13 19:37                             ` Dmitry A. Kazakov
2013-03-13 19:54                               ` Simon Wright
2013-03-13 20:54                                 ` Dmitry A. Kazakov
2013-03-13 21:28                                   ` Simon Wright
2013-03-14  9:16                                     ` Dmitry A. Kazakov
2013-03-14 16:42                                       ` Simon Wright
2013-03-14 17:05                                         ` Dmitry A. Kazakov
2013-03-13 22:12                                   ` Robert A Duff
2013-03-13 21:47                                 ` Jeffrey Carter
2013-03-13 21:09                               ` Randy Brukardt
2013-03-13 22:48                                 ` Shark8
2013-03-14 22:01                                   ` Randy Brukardt
2013-03-15  3:27                                     ` Shark8
2013-03-15 21:05                                       ` Randy Brukardt
2013-03-15 21:46                                         ` Robert A Duff
2013-03-16  5:52                                           ` Shark8
2013-03-16  7:41                                             ` Dmitry A. Kazakov
2013-03-16 16:55                                               ` Shark8
2013-03-16 17:36                                                 ` Dmitry A. Kazakov
2013-03-16 21:51                                                   ` Shark8
2013-03-17  9:36                                                     ` Dmitry A. Kazakov
2013-03-18 23:13                                                       ` Randy Brukardt
2013-03-19  9:12                                                         ` Dmitry A. Kazakov
2013-03-19 21:19                                                           ` Randy Brukardt
2013-03-20 11:21                                                             ` Dmitry A. Kazakov
2013-03-20 23:57                                                               ` Randy Brukardt
2013-03-21 10:30                                                                 ` Dmitry A. Kazakov
2013-03-21 23:27                                                                   ` Randy Brukardt
2013-03-22 16:07                                                                     ` Dmitry A. Kazakov
2013-03-22 20:10                                                                       ` Shark8
2013-03-22 20:51                                                                         ` Dmitry A. Kazakov
2013-03-22 23:34                                                                           ` Robert A Duff
2013-03-23  8:41                                                                             ` Dmitry A. Kazakov
2013-03-23  2:29                                                                           ` Nasser M. Abbasi
2013-03-23  2:33                                                                       ` Randy Brukardt
2013-03-23  4:44                                                                         ` Shark8
2013-03-25 22:24                                                                           ` Randy Brukardt
2013-03-26  1:15                                                                             ` Shark8
2013-03-23  9:53                                                                         ` Dmitry A. Kazakov
2013-03-25 22:58                                                                           ` Randy Brukardt
2013-03-26 10:52                                                                             ` Dmitry A. Kazakov
2013-03-26 21:31                                                                               ` Randy Brukardt
2013-03-27  9:37                                                                                 ` Dmitry A. Kazakov
2013-03-27 19:42                                                                                   ` Randy Brukardt
2013-03-28 13:50                                                                                     ` Dmitry A. Kazakov
2013-03-28 21:55                                                                                       ` Randy Brukardt
2013-03-29 12:26                                                                                         ` Dmitry A. Kazakov
2013-03-30  0:49                                                                                           ` Randy Brukardt
2013-03-30  2:55                                                                                             ` Shark8
2013-04-01 23:43                                                                                               ` Messaging question [was: Is this expected behavior or not] Randy Brukardt
2013-03-30  9:20                                                                                             ` Is this expected behavior or not Dmitry A. Kazakov
2013-04-02  0:40                                                                                               ` Randy Brukardt
2013-04-02  8:44                                                                                                 ` Dmitry A. Kazakov
2013-04-02 21:54                                                                                                   ` Randy Brukardt
2013-04-03  8:54                                                                                                     ` Dmitry A. Kazakov
2013-04-04  0:04                                                                                                       ` Randy Brukardt
2013-04-04  8:26                                                                                                         ` Dmitry A. Kazakov
2013-04-04 20:31                                                                                                           ` Randy Brukardt
2013-04-05  9:57                                                                                                             ` Dmitry A. Kazakov
2013-04-05 12:45                                                                                                               ` Stefan.Lucks
2013-04-05 12:49                                                                                                                 ` Stefan.Lucks
2013-04-05 14:19                                                                                                                   ` Dmitry A. Kazakov
2013-04-05 14:44                                                                                                                     ` Stefan.Lucks
2013-04-05 16:11                                                                                                                       ` Dmitry A. Kazakov
2013-04-05 19:02                                                                                                                         ` Stefan.Lucks
2013-04-05 19:34                                                                                                                           ` Dmitry A. Kazakov
2013-04-05 20:23                                                                                                                             ` Stefan.Lucks
2013-04-06  7:39                                                                                                                               ` Dmitry A. Kazakov
2013-04-07 18:10                                                                                                                                 ` Stefan.Lucks
2013-04-07 18:23                                                                                                                                   ` Dmitry A. Kazakov
2013-04-05 20:38                                                                                                                             ` Stefan.Lucks
2013-04-05 14:36                                                                                                                 ` Dmitry A. Kazakov
2013-04-05 15:16                                                                                                                   ` Stefan.Lucks
2013-04-05 16:29                                                                                                                     ` Dmitry A. Kazakov
2013-04-05 19:55                                                                                                                       ` Stefan.Lucks
2013-04-06  1:45                                                                                                                         ` Randy Brukardt
2013-04-06  7:54                                                                                                                         ` Dmitry A. Kazakov
2013-04-07 18:17                                                                                                                           ` Stefan.Lucks
2013-04-07 18:28                                                                                                                             ` Dmitry A. Kazakov
2013-04-08  7:48                                                                                                                               ` Stefan.Lucks
2013-04-08  8:59                                                                                                                                 ` Dmitry A. Kazakov
2013-04-08 15:35                                                                                                                                   ` Stefan.Lucks
2013-04-08 19:08                                                                                                                                     ` Dmitry A. Kazakov
2013-04-09  7:18                                                                                                                                       ` Stefan.Lucks
2013-04-09  8:17                                                                                                                                         ` Dmitry A. Kazakov
2013-04-09 15:20                                                                                                                                           ` Stefan.Lucks
2013-04-09 16:15                                                                                                                                             ` Dmitry A. Kazakov
2013-04-09 22:59                                                                                                                                             ` Randy Brukardt
2013-04-09 22:57                                                                                                                                           ` Randy Brukardt
2013-04-10  7:30                                                                                                                                             ` Dmitry A. Kazakov
2013-04-10  8:00                                                                                                                                             ` Root_String'Class? (Was: Is this expected behavior or not) Jacob Sparre Andersen
2013-04-10 21:48                                                                                                                                               ` Randy Brukardt
2013-04-09 22:53                                                                                                                                     ` Is this expected behavior or not Randy Brukardt
2013-04-09 22:45                                                                                                                                   ` Randy Brukardt
2013-04-10  7:37                                                                                                                                     ` Dmitry A. Kazakov
2013-04-10 22:15                                                                                                                                       ` Randy Brukardt
2013-04-11  7:33                                                                                                                                         ` Dmitry A. Kazakov
2013-04-11 22:37                                                                                                                                           ` Randy Brukardt
2013-04-12  7:47                                                                                                                                             ` Dmitry A. Kazakov
2013-04-13  0:26                                                                                                                                               ` Randy Brukardt
2013-04-13  0:35                                                                                                                                               ` Randy Brukardt
2013-04-13  7:07                                                                                                                                                 ` Dmitry A. Kazakov
2013-04-06  1:38                                                                                                                       ` Randy Brukardt
2013-04-06  1:20                                                                                                               ` Randy Brukardt
2013-04-06  5:20                                                                                                                 ` Usefulness of OOP (was Is this expected behavior or not) J-P. Rosen
2013-04-06 10:31                                                                                                                   ` Dmitry A. Kazakov
2013-04-06 18:43                                                                                                                     ` Georg Bauhaus
2013-04-07  7:00                                                                                                                 ` Is this expected behavior or not Dmitry A. Kazakov
2013-04-09 23:24                                                                                                                   ` Randy Brukardt
2013-04-10  8:20                                                                                                                     ` Dmitry A. Kazakov
2013-04-10 22:07                                                                                                                       ` Randy Brukardt
2013-04-11  7:59                                                                                                                         ` Dmitry A. Kazakov
2013-04-11 11:10                                                                                                                           ` Georg Bauhaus
2013-04-11 13:49                                                                                                                           ` J-P. Rosen
2013-04-11 15:07                                                                                                                             ` Dmitry A. Kazakov
2013-04-12  4:39                                                                                                                               ` J-P. Rosen
2013-04-12  8:00                                                                                                                                 ` Dmitry A. Kazakov
2013-04-12  9:09                                                                                                                                   ` J-P. Rosen
2013-04-12 17:00                                                                                                                                     ` Jeffrey Carter
2013-04-11 23:02                                                                                                                           ` Randy Brukardt
2013-04-12  8:17                                                                                                                             ` Dmitry A. Kazakov
2013-04-12  9:41                                                                                                                               ` Georg Bauhaus
2013-04-12 11:46                                                                                                                                 ` Dmitry A. Kazakov
2013-04-13 17:38                                                                                                                                   ` Georg Bauhaus
2013-04-13  0:22                                                                                                                               ` Randy Brukardt
2013-04-13  6:49                                                                                                                                 ` Dmitry A. Kazakov
2013-04-16  1:41                                                                                                                                   ` Randy Brukardt
2013-04-16  8:03                                                                                                                                     ` Dmitry A. Kazakov
2013-04-16 22:57                                                                                                                                       ` Randy Brukardt
2013-04-17  7:18                                                                                                                                         ` Dmitry A. Kazakov
2013-04-17  9:23                                                                                                                                           ` Georg Bauhaus
2013-04-17  9:57                                                                                                                                             ` Dmitry A. Kazakov
2013-04-17 19:38                                                                                                                                               ` Georg Bauhaus
2013-04-18 11:52                                                                                                                                                 ` Dmitry A. Kazakov
2013-04-19  2:16                                                                                                                                                   ` Randy Brukardt
2013-04-19  7:39                                                                                                                                                     ` Dmitry A. Kazakov
2013-04-19  9:07                                                                                                                                                   ` Georg Bauhaus
2013-04-19  9:11                                                                                                                                                     ` Georg Bauhaus
2013-04-19 12:09                                                                                                                                                     ` Dmitry A. Kazakov
2013-04-19 22:14                                                                                                                                                       ` Randy Brukardt
2013-04-20  6:39                                                                                                                                                         ` Dmitry A. Kazakov
2013-03-19  0:38                                                       ` Shark8
2013-03-19  8:53                                                         ` Dmitry A. Kazakov
2013-03-16 20:45                                             ` Robert A Duff
2013-03-16  9:29                                           ` Georg Bauhaus
2013-03-16 20:49                                             ` Robert A Duff
2013-03-14 22:41                             ` Florian Weimer
2013-03-12 23:21           ` Randy Brukardt
2013-03-12 23:14       ` Randy Brukardt
2013-03-11 20:43   ` Anh Vo
2013-03-11 22:32     ` Randy Brukardt
2013-03-11 22:38     ` Robert A Duff
2013-03-12  9:17   ` Dmitry A. Kazakov
2013-03-13  0:10     ` Shark8

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