user5069935
user5069935

Reputation:

Ada - one dimensional array operations

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?

EDIT:

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

Answers (2)

DeeDee
DeeDee

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

egilhh
egilhh

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

Related Questions