Reputation:
In reference to John Barnes' book "Programming in Ada 2012" (ISBN: 978-1-107-42481-4), P. 138 (section 8.6).
procedure ArrayOps is
type Bit_Row is array (Positive range <>) of Boolean;
A, B : Bit_Row (1 .. 4);
T : constant Boolean := True;
F : constant Boolean := False;
begin
A := (T, T, F, F);
B := (T, F, T, F);
A := A and B;
end ArrayOps;
I've added a simple wrapper around the minimal fragment the author provides, and this seems to compile and run as expected.
The author states that this can be done with "Many of the operators", implying arithmetical such as +
, *
, -
and /
.
I have attempted to convert this to the addition operator using Integer data types, but alas this does not compile...
procedure ArrayOps is
type Int_Row is array (Positive range <>) of Integer;
A, B : Int_Row (1 .. 4);
T : constant Integer := 1;
F : constant Integer := 0;
begin
A := (T, T, F, F);
B := (T, F, T, F);
A := A + B;
end ArrayOps;
The compiler error states: arrayops.adb:12:10: there is no applicable operator "+" for type "Int_Row" defined at line 2
. That is the only error. Clearly something is missing from my code, but the book doesn't mention this topic ever again. How may I enable array operations for operators other than the boolean operators?
I have amended the code as per @egilhh's answer, as that seems to be the minimal set of changes to solve the basic problem.
procedure ArrayOps is
type Int_Row is array (1 .. 4) of Integer;
function "+"(Left, Right : Int_Row) return Int_Row
is
Result : Int_Row;
begin
for I in Int_Row'Range loop --'
Result(I) := Left(I) + Right(I);
end loop;
return Result;
end "+";
A, B : Int_Row;
T : constant Integer := 1;
F : constant Integer := 0;
begin
A := (T, T, F, F);
B := (T, F, T, F);
A := A + B;
end ArrayOps;
This now works. However, I have accepted DeeDee's answer as that may be a best practice solution. Kudos to both :)
Upvotes: 4
Views: 99
Reputation: 5941
With "many operators" the book refers to the logical and relational operators. Only these operators are implicitly defined for one-dimensional array types as required by the language standard (see RM 4.5.1 (2) and RM 4.5.2 (1)).
For other operators, you'll need to implement them yourself:
arrayops.adb
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure ArrayOps is
type Int_Row is array (Positive range <>) of Integer;
A, B : Int_Row (1 .. 4);
T : constant Integer := 1;
F : constant Integer := 0;
---------
-- "+" --
---------
function "+" (A, B : Int_Row) return Int_Row is
begin
if A'Length /= B'Length then
raise Constraint_Error with "array lengths do not match";
end if;
declare
Result : Int_Row (1 .. A'Length);
begin
for I in Result'Range loop
Result (I) := A (A'First + I - 1) + B (B'First + I - 1);
end loop;
return Result;
end;
end "+";
---------
-- Put --
---------
procedure Put (A : Int_Row; Width : Natural := 0) is
use Ada.Integer_Text_IO;
begin
for I in A'Range loop
Put (A (I), Width);
end loop;
end Put;
begin
A := (T, T, F, F);
B := (T, F, T, F);
Put (A, 2); New_Line;
Put (B, 2); New_Line;
A := A + B;
Put ("--------- +"); New_Line;
Put (A, 2); New_Line;
end ArrayOps;
output
1 1 0 0
1 0 1 0
--------- +
2 1 1 0
Upvotes: 4
Reputation: 6430
"Many" does not mean "all"... Specifically he mentions and
, or
, xor
and not
for one-dimensional Boolean
arrays. Of course, those are just the predefined ones; there's nothing stopping you from defining your own operators. Take a look at P. 169 (section 10.2).
function "+"(Left, Right : Int_Row) return Int_Row
is
Result : Int_Row;
begin
for I in Int_Row'Range loop --'
Result(I) := Left(I) + Right(I);
end loop;
return Result;
end "+";
Upvotes: 2