From: Gene on
Seldom am I surprised by Ada semantics, but today they got me.

type Int_List_Type is array(Integer range <>) of Integer;

procedure Main is

function F(a : Int_List_Type) return Integer is
i : Integer;
begin
if a'Length <= 1 then
return a(1);
else
-- calculate i s.t. 1 <= i <= a'Last
-- with some algorithm; details irrelevant
...
return F(a(1..i - 1) & a(i + 1, a'Last));
end if;
end Calculate;

a : Int_List(1..100);

begin
-- yada yada; fill a with values
Put(Calculate(F(a)));
end;

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.

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?

Gene

From: Dmitry A. Kazakov on
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. 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?

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Florian Weimer on
* 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.
From: Jean-Pierre Rosen on
Gene a ýcrit :
> Seldom am I surprised by Ada semantics, but today they got me.
>
> type Int_List_Type is array(Integer range <>) of Integer;
>
> procedure Main is
>
> function F(a : Int_List_Type) return Integer is
> i : Integer;
> begin
> if a'Length <= 1 then
> return a(1);
> else
> -- calculate i s.t. 1 <= i <= a'Last
> -- with some algorithm; details irrelevant
> ...
> return F(a(1..i - 1) & a(i + 1, a'Last));
> end if;
> end Calculate;
>
> a : Int_List(1..100);
>
> begin
> -- yada yada; fill a with values
> Put(Calculate(F(a)));
> end;
>
> 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.
>
> 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?
>
Because the lower bound of a null array needs not belong to the subtype
used for indexing.

Note that you can force the lower bound by subtype conversion:
declare
Result : constant string := F(a(1..i - 1) & a(i + 1, a'Last));
subtype Force_Lower_To_1 is string (1 .. Result'length);
begin
return Force_Lower_To_1 (Result);
end;

--
---------------------------------------------------------
J-P. Rosen (rosen(a)adalog.fr)
Visit Adalog's web site at http://www.adalog.fr
From: Georg Bauhaus on
Dmitry A. Kazakov wrote:

> A more interesting question is why Empty'First does not raise any
> exception.

Because 'First does not denote an element?

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

? What's the bound of a range? (as opposed to a bounded array)

> 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?

Carrying the arguement further, how to reference an element
outside the machine's storage?