Version 1.4 of ai12s/ai12-0125-3.txt
!standard 5.2.1(0) 16-01-08 AI12-0125-3/02
!class Amendment 15-10-13
!status work item 15-10-13
!status received 15-09-22
!subject Add @ as a shorthand for the LHS of an assignment
Define @, which can be used in the right-hand side of an assignment
statement as a shorthand for the name of the left-hand side.
Incrementing, decrementing, scaling, etc., are all somewhat painful in
Ada, particularly if the object being updated has a long name, or
involves any sort of dynamic addressing:
My_Package.My_Array(I).Field := My_Package.My_Array(I).Field + 1;
Some sort of short-hand would be welcome, as it would ease both
readability and writability, while reducing the possibility of error,
such as unintended multiple evaluations of expressions in the name, or
mismatching array indices.
We define a new symbol, @, the target name which represents a constant view
of the left-hand side of an assignment.
Add after 3.3(21.1/3): [Editor's note: This is the list of items that are
defined to be constant. Since that list is defined to be exclusive, we have
to include target_name here.]
* a target_name of an assignment_statement when used in the
expression of the assignment (see 5.2.1);
[Editor's note: The "when used in the expression of the assignment" isn't
strictly necessary, as that is the only place a target_name is allowed. But
this is a forward reference and a causal reader might interpret this as
applying to the variable_name of the assignment -- which it does not.]
Add target_name to the syntax of Name in 4.1(2/3).
[Editor's note: We add a new syntax nonterminal because all of the other
kinds of name are defined that way, rather than by reference to other
subclauses as is done for a primary. We try to be consistent within
a clause, even if the Standard is not consistent for similar constructs.]
Add a new subclause:
5.2.1 Target name (@) shorthand
@, known as the target name of an assignment statement,
provides a shorthand to avoid repetition of potentially long
names in assignment statements.
Target_Name ::= @
Name Resolution Rules
Redundant[If a target_name T occurs in an assignment_statement A, the
variable_name V of A is a complete context.] T is a constant view
of V, having the nominal subtype of V.
AARM The Proof: The complete context rule is formally given in 8.6.
A target_name shall only appear in the expression of an
If a target_name with nominal subtype S appears in the expression of
an assignment statement A, then A is equivalent to a local anonymous
procedure having an in out parameter P of subtype S, with a
body being S with the variable_name being replaced by P, and
any target_names being replaced by the qualified expression
S'(P); followed by a call on the anonymous procedure with the
actual parameter being the variable_name of S.
[Editor's note: We use a qualified expression here to ensure the
replacement has the semantics of a constant view. I would have preferred
to avoid that (a target_name is a constant view by rule), but just using
P here is misleading, especially if someone is doing expression
analysis after this expansion. We could probably drop the explicit
definition of @ as a constant view, since this expansion would have
that effect anyway, but it seems valuable to emphasize that to readers.]
AARM Reason: This equivalence defines all of the Dynamic Semantics
for these assignment statements. We use the parameter to bind the
variable_name; it is evaluated only once.
For example, the expression
My_Array(I) := @*2 + @/2;
would be equivalent to
procedure [Anon] ([Target] : in out [Target_Subtype]) is
[Target] := [Target_Subtype]'([Target])*2 +
[Anon] ([Target] => My_Array(I));
where all of the identifiers in square brackets are anonynous
End AARM Discussion.
Add after 8.6(9/4):
* The *variable_*name of an assignment_statement *A*, if the expression of
A contains one or more target_names.
X := @ + 1; --
A(I) := Integer'Max (@, 10); --
The occurrence of a target_name (@) in an assignment makes the
/variable_/name (the left-hand side of the assignment) a complete context.
This avoids complicating resolution unnecessarily; otherwise it would be
possible for the LHS to be overloaded in such a way that the uses of @
determine which possibility is correct. This is especially complicated
as @ has to resolve the same as the LHS, whereas a simple textual substitution
would not have that property. We avoid the complication by legislating it
This is potentially a maintenance hazard, as introducing @ into an
assignment_statement potentially could make it illegal. However, since
stand-alone objects and parameters cannot be overloaded, this will rarely make
a difference in practice (there is rarely more than one interpretation of
the LHS of an assignment).
The expansion in terms of an anonymous procedure preserves the possibility of
erroneous execution in obscure cases:
type Mutable (D : Boolean := True) is record
case D is
when True =>
I : Integer;
when False =>
F : Float;
Obj : Mutable;
function Fooey return Integer is
Temp : Integer := Obj.I;
Obj := (D => False, F => Float(Temp));
Obj.I := @ + Fooey; --
Obj.I := Obj.I + Fooey; --
In these assignments, the I component doesn't exist when it is written. Ada
doesn't try to prevent that, both (1) and (2) are erroneous.
We considered using a renames formulation instead:
Obj.I := @ + 1;
being the same as:
<Target> : renames Integer := Obj.I; --
<Target> := <Target> + 1;
However, this doesn't work in this case, as the renames of a discriminant
dependent-component (like (3)) is illegal. Since the update to the I component
is the sort of use this feature is constructed for, making it illegal seems
too restrictive. (And this is not a new kind of erroneous execution, as
Note that the subprogram call introduced by this formulation could introduce
an extra possibility of a failing subtype check, but this can happen only if
the value of the variable_name is invalid or a predicate has a side-effect.
In these cases, reading the variable_name isn't going to be safe anyway, so
the effect is mainly to make a latent error more visible.
The target_name is a constant view of the LHS of the assignment. We do this
mainly so that the use of @ does not trigger the Taft anti-aliasing rules
(6.4.1). A side-effect is that the target object cannot be modified directly
via @, preventing problems. We accomplish this by defining the target_name
to expand to a qualified_expression; that expression could introduce an
extra exception, but only if a predicate has a side-effect (the subtype
conversion was already done by the parameter passing, this is just a repeat).
This proposal is better than AI12-0125-2, as
(1) It is more flexible; it can be used in function calls other than operators
(as shown by the 'Max example above).
(2) There is a positive indication that this notation is being used (the
addition of an @ as opposed to deleting an '=');
(3) It doesn't (directly) depend on visibility of anything; it's always
available unless the LHS of the assignment is overloaded.
It is different than the proposal of AI12-0125-2: (whether these are advantages
or disadvantages are in the eye of the beholder -- the author finds these to be
(1) Only one new lexical symbol is needed, rather than many.
(2) It doesn't have an "obvious" extension to a user-defined version, which
avoids a nasty slippery slope.
(3) It doesn't look like we're out of ideas by stealing groddy parts of other
This proposal is the same as the proposal AI12-0125-2 in the following ways:
(1) The semantics is described in terms of an anonymous procedure.
(2) The left-hand side of the assignment is treated as a complete context,
meaning that in rare cases, introducing @ into an assignment (or using
:+) would make the assignment illegal.
These should be considered issues with solving the problem as opposed to
negatives against a particular proposal.
(3) Both are only one character different from very different expressions:
Obj:=@+1; vs. Obj:=+1; --
Obj:+1; vs. Obj:=+1; --
Of course, writing without whitespace is discouraged in Ada, but these are
legal expressions regardless of common practice. This problem could be
eliminated for this proposal by using more than one character for the target
name (as the original proposal <<>> did).
** TBD **
ACATS B and C-Tests would be needed.
Questions? Ask the ACAA Technical Agent