5

A for loop can be done in Ada using a range with a start and an end point:

for I in 0..10 loop
(...)
end loop;

I know, it's possible doing the for loop using two variables describing the range:

for I in range_start..range_end loop
(...)
end loop;

Is it also possible to store the range in one variable?, like:

for I in my_range loop
(...)
end loop;

Which type has the variable *my_range* to be?

Edit: Let's say I want to use this variable as a parameter in a subprogram: So the subprogram has this loop which iterates over the range. I'd rather use two variables describing the range instead of using generics, because generics would cause in higher effort. But I think using one variable describing the range would cause in a higher readability, that's why I'm asking that question.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
clx
  • 794
  • 2
  • 8
  • 19

5 Answers5

3

If your variable is an array, then you can iterate over its range via:

for I in Arr_Var'Range loop
   ...
end loop;

If you're interested in iterating over the elements of a container, e.g. array, vector, map, etc., and don't care about the index, you can use generalized looping (Ada 2012 only):

for Elem of Container loop
   ...
end loop;
Marc C
  • 8,664
  • 1
  • 24
  • 29
  • The variable isn't an array. But I could use a dummy array for the range, right? – clx Jan 21 '13 at 16:10
  • Well, you could, but having a bogus array just for that would be highly discouraged. I edited my answer to add a brief example on how to do this with the First and Last attributes if the variable is of a discrete type. – Marc C Jan 21 '13 at 16:16
  • @Marc, `'First` & `'Last` can't be applied to simple variables - only [arrays & (sub)types](http://www.ada-auth.org/standards/12rm/html/RM-K-2.html#p66). – Simon Wright Jan 21 '13 at 17:20
2

Use a range type, something along these lines:

type Range_Type is range -5 .. 10;
...
for A in Range_Type loop

See the complete example in here.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • But if I'd like to use the range as a parameter for a subprogram I had to use generics, right? So I think this solution makes it more complicated than using two variables... – clx Jan 21 '13 at 16:09
  • A range is a type like any other, you either pass along the range or pass along the two points and build the range where needed – Óscar López Jan 21 '13 at 16:30
1

Hmmm. It looks like you may be (perhaps unknowingly) a devotee of Andrei Alexandrescu. He's argued strongly for languages to make ranges a first-class type, and the removal of "iterators" as a programming paradigm.

It would be interesting to see what an Ada implementation of this would look like. Unless I'm missing something, that's not the way Ada 2012 went.

Community
  • 1
  • 1
T.E.D.
  • 44,016
  • 10
  • 73
  • 134
1

If you want to pass around an object containing the range, you can wrap Start and End in a record. Inside the subprogram you can locally declare a new [sub]type bounded by the range.

type Range_Type is range TheRange.Start .. TheRange.end;
  • This must be more trouble than creating a generic! – Simon Wright Jan 23 '13 at 17:01
  • @Simon : +1 and true. I think I subconsciously slipped into VHDL where generics are more restrictive. The record would at least be portable to VHDL... –  Jan 24 '13 at 11:47
1

My count says you need 4 more lines to create a generic subprogram than a plain one:

generic                             -- extra
   type Bounds is (<>);             -- extra
procedure R;

procedure R is
begin
   for J in Bounds'Range loop
      null;
   end loop;
end R;

with R;
procedure P is
   type Rng is range 1 .. 10;       -- extra
   procedure A is new R (Rng);      -- extra
begin
   A;
end P;

which doesn't seem so bad.

But, usually an iteration is iterating over something (an array, ...): if so, you can derive the iteration range from the thing that's being iterated over.

Simon Wright
  • 25,108
  • 2
  • 35
  • 62