From: Florian Weimer on
* Georg Bauhaus:

> Florian Weimer wrote:
>
>> Even more problematic is the empty array whose index type
>> is an enumeration type with just one enumeration literal.
>
> This looks like a formalist's problem to me.

To some extent, sure. Furtunately, these arrays do not occur in
practice. However, you have to think about this problem for a moment
when you write generic containers.
From: Robert A Duff on
"Gene" <gene.ressler(a)gmail.com> writes:

> Seldom am I surprised by Ada semantics, but today they got me.
>
> type Int_List_Type is array(Integer range <>) of Integer;

"Positive range <>" or "Natural range <>" is probably a better idea.
If you have an unconstrained array such that Index_Type'First =
Index_Type'Base'First, you will run into trouble with empty arrays.

> return F(a(1..i - 1) & a(i + 1, a'Last));

> The gotcha is that when (and only when) i is determined to be zero, the
> concatenation in the recursive call to F produces a starting index of 2
> rather than 1. Of course this causes the base case test to raise an
> exception in the next recursive call. This is in accordance with the
> ALRM and GNAT implements it perfectly.

Consider:

X: String(-99 .. -10_000); -- empty string
Y: constant String := X & "Hello world."

Ada requires the bounds of a String to be in Positive, EXCEPT when it's
an empty String. So X'First = -99, but Y'First can't be -99.

Your suggestion would make sense if Ada didn't allow weird things like
String(-99 .. -10_000). It shouldn't -- allowing such things just
causes confusion and bugs. The rule should be that 'First of every
String is exactly 1. The 'Last should be in Positive, except in the
empty string case, where the bounds should be exactly 1..0.

The syntax for declaring String could be:

type String(Length: Natural) is array (Positive range 1..Length)
of Character;

No need for the "range <>" syntax in this language!

There's also an efficiency advantage: the dope can be just one word
instead of two, and the code to calculate 'Length could be branch free.

Note that Ada 200X has a Vectors generic container package, which
implements growable arrays. If you pass in Integer as the index type,
you will get Constraint_Error at instantiation time, for this very
reason. For the same reason, you can't pass an enumeration or modular
type as the index type -- empty vectors wouldn't work.

> Yes I know how to recode this to use a'First instead of 1 as needed.
>
> Nonetheless the rule seems silly: When a leading zero-length array is
> catenated to another array the result takes on the starting index of
> the _second_ operand. This doesn't make sense to me. Why not use the
> starting index of the zero-length array?

- Bob
From: Robert A Duff on
"Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> writes:

> On 31 Aug 2005 20:16:43 -0700, Gene wrote:
>
> > Nonetheless the rule seems silly: When a leading zero-length array is
> > catenated to another array the result takes on the starting index of
> > the _second_ operand. This doesn't make sense to me. Why not use the
> > starting index of the zero-length array?
>
> Because that might be ill-defined, I guess.
>
> A more interesting question is why Empty'First does not raise any
> exception.

Heh? You want this:

procedure Put(S: String) is
begin
for I in S'First..S'Last loop -- equivalent to S'Range
Put_Char(S(I));

to crash when S = ""?

>... After all, there is no any lower bound of an empty index range.

In Ada, every range, and every array, has both a lower and an upper
bound.

> Provided, that empty arrays are all same, of course.

Depends on what you mean by "same". ;-) Different empty arrays can
have different bounds -- but "=" returns True!

>... If not, then another
> interesting question would appear: how to make an empty array with the
> lower bound Integer'First?

You can't.

You should always make sure Index'First > Index'Base'First when using
the "Index range <>" syntax. (But you don't need to do that when you
have a constrained array -- "...array(Index) of ...".)

- Bob
From: Robert A Duff on
Florian Weimer <fw(a)deneb.enyo.de> writes:

> * Dmitry A. Kazakov:
>
> > A more interesting question is why Empty'First does not raise any
> > exception. After all, there is no any lower bound of an empty index range.
> > Provided, that empty arrays are all same, of course. If not, then another
> > interesting question would appear: how to make an empty array with the
> > lower bound Integer'First?
>
> You can't. Even more problematic is the empty array whose index type
> is an enumeration type with just one enumeration literal.

Why would you want an unconstrained array indexed by enumeration type?
And why would you want an empty array if the array type is constrained?

As for modular types -- well, they're an abomination all around.
It makes no sense whatsoever to have an index type for an unconstrained
array such that Index'Pred(Index'First) > Index'First!

- Bob
From: Dmitry A. Kazakov on
On 01 Sep 2005 12:04:17 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> writes:
>
>> On 31 Aug 2005 20:16:43 -0700, Gene wrote:
>>
>>> Nonetheless the rule seems silly: When a leading zero-length array is
>>> catenated to another array the result takes on the starting index of
>>> the _second_ operand. This doesn't make sense to me. Why not use the
>>> starting index of the zero-length array?
>>
>> Because that might be ill-defined, I guess.
>>
>> A more interesting question is why Empty'First does not raise any
>> exception.
>
> Heh? You want this:
>
> procedure Put(S: String) is
> begin
> for I in S'First..S'Last loop -- equivalent to S'Range
> Put_Char(S(I));
>
> to crash when S = ""?

Yes. It is in my view no different from

Y := X / X;

crashing when X=0. The former should be

for I in S'Range loop -- is not equivalent to S'First..S'Last when S is ""

The latter should be:

Y := 1; -- is not equivalent to X / X when X is 0

>>... After all, there is no any lower bound of an empty index range.
>
> In Ada, every range, and every array, has both a lower and an upper
> bound.

That's exactly the problem! (:-))

>> Provided, that empty arrays are all same, of course.
>
> Depends on what you mean by "same". ;-) Different empty arrays can
> have different bounds -- but "=" returns True!

Ditto. Empty sets are indistinguishable. They have no identity. Ada's empty
arrays are different with all nasty consequences of that.

>>... If not, then another
>> interesting question would appear: how to make an empty array with the
>> lower bound Integer'First?
>
> You can't.

Which is bad.

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