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.