Target Name Symbol (@)

Note

Target name symbol is supported by

  • GNAT Community Edition 2019

  • GCC 9

Ada 2022 introduces a new symbol, @, which can only appear on the right hand side of an assignment statement. This symbol acts as the equivalent of the name on the left hand side of that assignment statement. It was introduced to avoid code duplication: instead of retyping a (potentially long) name, you can use @. This symbol denotes a constant, so you can't pass it into [in] out arguments of a subprogram.

As an example, let's calculate some statistics for My_Data array:

    
    
        
pragma Ada_2022; package Statistics is type Statistic is record Count : Natural := 0; Total : Float := 0.0; end record; My_Data : array (1 .. 5) of Float := (for J in 1 .. 5 => Float (J)); Statistic_For_My_Data : Statistic; end Statistics;

To do this, we loop over My_Data elements:

    
    
        
pragma Ada_2022; with Ada.Text_IO; procedure Main is type Statistic is record Count : Natural := 0; Total : Float := 0.0; end record; My_Data : constant array (1 .. 5) of Float := (for J in 1 .. 5 => Float (J)); Statistic_For_My_Data : Statistic; begin for Data of My_Data loop Statistic_For_My_Data.Count := @ + 1; Statistic_For_My_Data.Total := @ + Data; end loop; Ada.Text_IO.Put_Line (Statistic_For_My_Data'Image); end Main;

Each right hand side is evaluated only once, no matter how many @ symbols it contains. Let's verify this by introducing a function call that prints a line each time it's called:

    
    
        
pragma Ada_2022; with Ada.Text_IO; procedure Main is My_Data : array (1 .. 5) of Float := (for J in 1 .. 5 => Float (J)); function To_Index (Value : Positive) return Positive is begin Ada.Text_IO.Put_Line ("To_Index is called."); return Value; end To_Index; begin My_Data (To_Index (1)) := @ ** 2 - 3.0 * @; Ada.Text_IO.Put_Line (My_Data'Image); end Main;

This use of @ may look a bit cryptic, but it's the best solution that was found. Unlike other languages (e.g., sum += x; in C), this approach lets you use @ an arbitrary number of times within the right hand side of an assignment statement.

Alternatives

In C++, the previous statement could be written with a reference type (one line longer!):

auto& a = my_data[to_index(1)];
a = a * a - 3.0 * a;

In Ada 2022, you can use a similar renaming:

declare
   A renames My_Data (To_Index (1));
begin
   A := A ** 2 - 3.0 * A;
end;

Here we use a new short form of the rename declaration, but this still looks too heavy, and even worse, it can't be used for discriminant-dependent components.

References