Marcello90
Marcello90

Reputation: 1343

Variant records: Use components multiple times

I created the following example code:

type Category is (A, B, C);

type My_Record (The_Category : Category) is record
    case The_Category is
        when A =>
            A : Natural;
        when B =>
            B : Integer;
        when C =>
            A : Natural;
            B : Integer;
    end case;
end record;

The code is obviously not valid in Ada because I am getting two compiler errors: "A/B" conflicts with declaration at line ...

Why is such definition of a variant record not supported in Ada? I think it could be useful. Are there other ways to model this kind of data structure?

Upvotes: 1

Views: 360

Answers (2)

Jacob Sparre Andersen
Jacob Sparre Andersen

Reputation: 6611

It is not supported because it might confuse a reader (or a developer).

The fields in the different branches are logically different fields, so using the same name would be confusing.

(This is my explanation. If there exists an official one, you can find it in the Ada 83 Rationale.)

I practice you do something like this:

type Categories is (A, B, C);

type Data (Category : Categories) is record
   case Category is
      when A =>
         Identifier_1 : Natural;
      when B =>
         Identifier_2 : Integer;
      when C =>
         Identifier_3 : Natural;
         Identifier_4 : Integer;
      end case;
   end record;

You have to come up with some actual, sensible naming yourself, as I don't know which problem you're trying to solve.

Upvotes: 1

LambdaBeta
LambdaBeta

Reputation: 1505

I ran into this problem recently. This is a case of Ada having your back. The Adaic (Pythonic equivalent?) way would be something like:

type Category is (A, B, C);
type A_Data is
    record
        A : Natural;
    end record;
type B_Data is
    record
        B : Integer;
    end record;
type C_Data is
    record
        A : Natural;
        B : Integer;
    end record;

type My_Record (The_Category : Category) is record
    case The_Category is
        when A =>
            A : A_Data;
        when B =>
            B : B_Data;
        when C =>
            C : C_Data;
    end case;
end record;

While verbose, this provides strong typing as to what you have access to. The usage is nearly identical, the main difference is that in the C category things look uniform:

case My_Object.The_Category is
    when A => 
        Use_Integer (My_Object.A.A);
    when B => 
        Use_Natural (My_Object.B.B);
    when C =>
        Use_Integer (My_Object.C.A);
        Use_Natural (My_Object.C.B);
end case;

A lot of people take some time to get used to Ada's verbosity, but over time you learn to love it. This larger interface compiles to nearly identical code and is much more open to extensibility (what if category A items now also need a float? instead of changing all A category items, just change the A_Data type).

Upvotes: 1

Related Questions