My code is below. The compiler won’t let me use the discriminant var
to control the size of the string name
.
procedure p is
type int is range 1 .. 10;
type my (var : int) is record
name : string (1 .. var); -- this var here is bad, why?
end record;
hh : my(6);
begin
put (hh.name);
end p;
The error messages are
p.adb:4:23: expected type "Standard.Integer"
p.adb:4:23: found type "int" defined at line 2
It's due to Ada strong typing. Ada allows you to declare new integer and floating-point types which are not compatible with each other. The original intent was to prevent accidentally using values with one meaning as if they had a totally unrelated meaning, e.g.
type Length is digits 15; -- in meters
type Mass is digits 15; -- in kilograms
L : Length;
M : Mass;
M := L; -- error, caught at compile time
The compiler catches this statement that doesn't make any sense because a "mass" variable can't hold a length. If everything were just Float
or Long_Float
the compiler wouldn't be able to catch it.
What you've done is to create another integer type, int
. As in the above example, values of your new type can't automatically be converted to Integer
, which is the type of the index of String
. (String
is actually defined as array (Positive range <>) of Character with Pack;
, but Positive
is a subtype of Integer
, and values can be automatically converted between Positive
and Integer
since they are really subtypes of the same base type.)
Unfortunately, this isn't allowed either:
type my(var : int) is record
name : string (1 .. Integer(var)); -- this var here is bad why?
end record;
because of an Ada rule that the discriminant has to appear alone in this context. So your only option is to make int
a subtype:
subtype int is Integer range 0 .. 10;
type my(var : int) is record
name : string (1 .. var); -- this var here is bad why?
end record;