From: Georg Bauhaus on
Georg Bauhaus wrote:

> A range with A'Last > A'First is not wrong,
A'First > A'Last
From: Jeffrey R. Carter on
Gene wrote:

> -- 'First is not always 1. How marginally
> Ada!

'First is not always 1 (or 0, or X) is a basic concept in Ada. It's only if you
don't know, or forget, this, and assume the behavior you learned in lesser
languages, that you have problems.

I came to Ada from Pascal, so I was used to the lower bound not being fixed, and
the discovery of attributes simply made life easier. Had I come directly from
FORTRAN, for example, I might have had more difficulty, because it would have
involved grasping both the idea of user-defined lower bounds and the idea of
attributes.

--
Jeff Carter
"I'm particularly glad that these lovely children were
here today to hear that speech. Not only was it authentic
frontier gibberish, it expressed a courage little seen
in this day and age."
Blazing Saddles
88
From: Robert A Duff on
tmoran(a)acm.org writes:

> >I completely agree with the marginal utility of other-than-1 least
> >array indices.
> I strongly disagree. While not dirt common, other 'firsts in
> declarations do occur. -n .. +n comes to mind.

Heh? "Marginal utility" means the same as "not dirt common"!

My suggestion was that the language should _allow_ the programmer to fix
the lower bound for an array type. And/or the upper bound. In Ada, you
can fix both or neither -- but not one or the other.

Anyway, you'd still be allowed to do your -n..+n thing, in the rare
cases where that's useful.

>... If you are going to
> handle slices, you have to assume 'first /= 1 anyway,...

No, I don't. ;-)

Slices should slide to the lower bound. The Ada rule breaks
abstraction:

procedure P(X: String) is
begin
...
end P;

Y: String := "Hello, world!";

P(Y(3..4));

Inside the body of P, X is just a String -- we don't (or shouldn't) know
that it's a substring of Y. So we can't possibly make any sense (inside
P) of the fact that X'First = 3. Index 3 from what?

If I ran the circus, X'First would be 1.

>... so you're not losing
> much by allowing it in declarations. Using 'first instead of 1 also makes
> it simple to change between integer and enumeration value indexes. The
> way Ada.Text_IO.Get_Line (et al) returns Last, which works even if you
> passed it a slice, has surely prevented many an error as compared to other
> languages which would likely return a count (since "all arrays start at
> x") and depend on the programmer to do any arithmetic needed to turn it
> into an index. And if you started all arrays at 1,

I wouldn't insist on starting _all_ arrays at 1, but I think it makes
sense for _many_ arrays, including String.

>... you probably wouldn't
> allow the idiom
> subtype cards is string(1 .. 80);
> subtype sequence is range 73 .. 80;
> ...
> if card(sequence) = (sequence=>' ') then

Why not? In Ada, "=" doesn't care about the bounds -- just the length.

- Bob
From: Robert A Duff on
"Jeffrey R. Carter" <spam(a)spam.com> writes:

> Gene wrote:
>
> > -- 'First is not always 1. How marginally
> > Ada!
>
> 'First is not always 1 (or 0, or X) is a basic concept in Ada. It's only
> if you don't know, or forget, this, and assume the behavior you learned
> in lesser languages, that you have problems.
>
> I came to Ada from Pascal, so I was used to the lower bound not being
> fixed,

Heh? The lower (and upper!) bound of all array types in Pascal is
fixed. And it has to be fixed at a static value. Every array object of
a given type has the same fixed bounds.

(Well, some version of Pascal added conformant arrays, which relaxed
this requirement for formal parameters.)

It's true that the lower bound doesn't have to be 1, or any other
particular value, but it has to be static, and it is fixed for that
array type.

I don't think anybody would suggest that _all_ arrays in Ada must start
at 1. That would preclude arrays indexed by enumeration types, which
don't have a concept of 1.

>... and the discovery of attributes simply made life easier. Had I
> come directly from FORTRAN, for example, I might have had more
> difficulty, because it would have involved grasping both the idea of
> user-defined lower bounds and the idea of attributes.

- Bob
From: Robert A Duff on
"jimmaureenrogers(a)worldnet.att.net" <jimmaureenrogers(a)worldnet.att.net> writes:

>...Concatenating array A whose indices represent
> the null set with array B whose indices represent some non-null set
> should always result in an array whose indices are a non-null set.

Agreed.

> Moreover, the most efficient and logical merging of the two sets
> results in a set idenitcal to the indices of B.

I don't agree that's most logical, but I suppose that's somewhat a
matter of taste.

But the Ada rule is _certainly_ not the "most efficient"!

If all Strings start at 1, then we reduce the size of the array dope by
4 bytes. If the average String length in your program is, say, 20
bytes, you're saving 4 bytes for every 24, or about 17% of the memory
use, which is substantial. Saving memory generally speed up programs
due to cache effects.

It's really annoying to me that the compiler stores zillions of copies
of the number 1 in memory (one copy for each String object), just
because some oddball String _might_ start at other than 1.

Furthermore, bounds checking would be much faster, because there would
be no need to load the lower-bound from memory. Memory loads are often
slow on modern machines.

Furthermore, consider the code generated for 'Length: In Ada, it's
something like:

if X'First <= X'Last then
X'Last - X'First + 1
else
0
end if;

If X'First were known to be always 1, it would be:

X'Last

If X'First were known to be always 17, it would be:

X'Last - 16

These latter are branch-free code sequences. Branches are often slow on
modern machines.

- Bob