What is the idiomatic way of specifying a range with an invalid value? [closed]

Solution 1:

I like to use a variant record in situations like this. It allows you to specify that an ID only exists if the Valid discriminant is set to True. It also allows Ada's strong type checking to enforce that invariant (I.E. if you try to access the ID of an invalid core, the code will raise an exception).

with Ada.Text_IO; use Ada.Text_IO;

procedure Hello is

    type Core_Identifier is new Positive range 1 .. 10;

    type Core (Valid : Boolean := False) is record
        case Valid is
            when True  => ID : Core_Identifier := 1;
            when False => null;
        end case;
    end record;
    
    Invalid_Core : constant Core := (Valid => False);
    
    -- Constructing function
    function Make_Core(ID : Core_Identifier) return Core
        is (Valid => True, ID => ID);
    
    -- Various initialization methods
    Core_1 : Core := Invalid_Core;
    Core_2 : Core := (Valid => True, ID => 6);
    Core_3 : Core := Make_Core(9);
    Core_4 : Core := (Valid => False);

begin
    Put_Line("Hello, world!");
  
    if not Core_1.Valid then
        Put_Line("Core 1 invalid");
    else
        Put_Line("Core 1 ID:" & Core_1.ID'Image);
    end if;
    
    if not Core_2.Valid then
        Put_Line("Core 2 invalid");
    else
        Put_Line("Core 2 ID:" & Core_2.ID'Image);
    end if;
    
    if not Core_3.Valid then
        Put_Line("Core 3 invalid");
    else
        Put_Line("Core 3 ID:" & Core_3.ID'Image);
    end if;
    
    if not Core_4.Valid then
        Put_Line("Core 4 invalid");
    else
        Put_Line("Core 4 ID:" & Core_4.ID'Image);
    end if;
    
end Hello;