Version 1.2 of ai05s/ai05-0187-1.txt

Unformatted version of ai05s/ai05-0187-1.txt version 1.2
Other versions for file ai05s/ai05-0187-1.txt

!standard 5.2.1 (0)          09-11-03 AI05-0187-1/01
!class amendment 09-11-03
!status work item 09-11-03
!status received 09-11-02
!priority Low
!difficulty Medium
!subject Shorthand for assignments with expressions naming target
!summary
A syntactic shorthand is introduced for assignment statements with expressions that include references to the target object.
!problem
It would be useful to have a shorthand for an assignment that updates its target object with an expression involving the target.
That is, for common assignments of a form such as:
<target-object> := <target-object> <some-operator> <some-value>;
or even more generally of the form:
<target-object> := <some expression which references target-object>;
the objective is to be able to write this without repeating the name of the target object.
The motivation here would be to aid readability, because often such assignments involve an object with a longish identifier (as Ada tends to encourage) or a complex compound name, and repeating the full name in the assignment expression is unwieldy and tends to make the statement too heavy and hence less readable.
!proposal
C and C++ allow shorthand forms for assignment such as "SomeObject += 1", and the proposal is to add a similar capability in Ada. This could be done using the same kind of syntactic notation as C (e.g., A +:= B), that would allow cases involving binary operators, or using a more general approach that would work for other forms of expression, by adding a new form of primary that would stand for the left-hand side. The latter alternative would permit arbitrary use of the target object's name on the assignment's right-hand side (e.g., Target_Object := Func (T_O)).
(Note: There are some ARG members who prefer the first approach, and others who prefer the second, so further discussion is needed before writing up any details.)
!wording
** TBD **
!discussion
** TBD **
!examples
** TBD **
!ACATS test
ACATS C-Tests are needed to check this feature.
!appendix

From: Gary Dimukes
Sent: Monday, November 2, 2009  12:57 PM

While we're on the subject of minor proposals to consider for the next revision,
and since this is the last opportunity to put them on the table, there's one
that I'd like to float that pops up in my mind from time to time.

It would be nice to have a shorthand for making an assignment that updates its
target object using an expression that involves the target.

That is, for common assignments of a form such as:

    <target-object> := <target-object> <some-op> <some-value>;

to be able to write this without repeating the name of the target object.

The motivation here would be to aid readability, because often such assignments
involve an object with a longish identifier (as Ada tends to encourage) or a
complex compound name, and repeating the full name in the assignment expression
is unwieldy and tends to make the statement too heavy and hence less readable.

C and C++ allow shorthand forms for assignment such as "SomeObject += 1", and
I'm proposing to allow something similar, but more general, for Ada. Rather than
extending the syntax for the assignment token, I would add a new form of primary
that would stand for the left-hand side.  This would permit arbitrary use of the
target object's name on the right-hand side (e.g., Target_Object := Func (T_O).

If such a feature were to be added, the tricky part is to come up with a
reasonable syntax for denoting the object.  Adding a new reserved word
presumablby won't fly (and there aren't any suitable existing reserved words),
and using an identifier for this would be a bad idea in any case.  Some short
but reasonably distinctive and obtrusive token is what's needed.  One fairly
obvious choice would be Ada's existing <> token.  That won't work though,
because it clashes with Ada 05's addition of box defaults in aggregates (unless
we were to syntactically restrict the new token's use, though I wouldn't
recommend that).  In the absence of any obvious existing token, and for purposes
of discussion (if there's any interest in such), I'll suggest a new compound
delimiter <<>> as a strawman, formed by sticking the existing left and right
label brackets together.  (Another choice could be '$', but that might be
considered too U.S.-centric;-)

The only other issue I see is to define the semantics of evaluating the symbol
denoting the target object.  It could be defined as a textual macro, so each
occurrence of the name would be reevaluated, but I believe the more appropriate
semantics would be to bind the name once, when the left-hand side name is
evaluated, making it equivalent to a renaming.  So each occurrence in the
assignment expression denotes the value of the single object determined by the
target name.  (This means requiring evaluation of the target object before the
expression, but that seems fine.)

Is there any interest in considering this proposal?  If so, I can take care of
drafting the AI.

****************************************************************

From: Tucker Taft
Sent: Monday, November 2, 2009  1:16 PM

I'd be more interested in just allowing the "<operator>=" syntax:

   X <operator>= Y;

would be equivalent to

   X := X <operator> Y;

except of course "equivalent" is never really just "equivalent" ;-).

Inventing some other syntax to mean the LHS is just making Ada harder to read
for non-Ada folks, while adding "<operator>=" would make it easier for non-Ada
folks to learn to read (and write) Ada.

****************************************************************

From: Randy Brukardt
Sent: Monday, November 2, 2009  1:29 PM

> Is there any interest in considering this proposal?  If so, I can take
> care of drafting the AI.

I'm mildly interested in this idea.

I'm not at all interested in Tucker's suggestion of copying C++, because I find
that it is quite common to need this in function calls:

     Target := Func(Target, ...);

Given Ada's equivalence of operators to functions, you sould have to be able to
handle user-defined operators in a :=+ operator anyway. Moreover, the resolution
would be messy (you'd have to handle operators where the Right operand is a
different type). And that would give an unnatural incentive to name functions as
operators if they commonly occurred in this form -- that seems exactly wrong.

(We'd also need to add three character or more delimiters, something Ada does
not already have. I don't know if adding new delimiters is actually a problem,
but it surely would add to the costs of a new feature.)

If Ada can do something *better* that existing languages, we at least ought to
consider that. Blindly copying other ideas does little to enhance the case for
using Ada.

****************************************************************

From: Steve Baird
Sent: Monday, November 2, 2009  5:59 PM

> I'd be more interested in just allowing the "<operator>=" syntax:
...

If we want to go with this approach, as
opposed to the more general approach that Gary and Randy were discussing, I
think a better way to define the semantics of
    <lhs> <operator>= <opnd2>;
via an equivalence is in terms of an implicit rename declaration, as in
    declare
       <anonymous> : <lhs>'Type renames <lhs>;
    begin
       <anonymous> := <anonymous> operator <opnd2>;
    end;

****************************************************************

From: Robert Dewar
Sent: Monday, November 2, 2009  11:11 PM

> I'd be more interested in just allowing the "<operator>=" syntax:
...

I agree that a simple form is better, though I think the
A68 syntax is a better choice for Ada

     X +:= 1;

I like the assignment symbol appearing, and in fact this is a better analog of
the C practice than

    X += 1;

****************************************************************

From: Robert Dewar
Sent: Monday, November 2, 2009  11:12 PM

> I'm not at all interested in Tucker's suggestion of copying C++,
> because I find that it is quite common to need this in function calls:
>
>      Target := Func(Target, ...);

Yes, but I still find the proposal unwieldy and ugly, and I think I prefer to
see things spelled out in a case like this.

> If Ada can do something *better* that existing languages, we at least
> ought to consider that. Blindly copying other ideas does little to
> enhance the case for using Ada.

I don't think this fancy proposal *is* better, I think it is too obscure.

****************************************************************

From: Tucker Taft
Sent: Monday, November 2, 2009  11:37 PM

I guess I just find "+:=" uglier than "+=".
Also, Algol 68 had to distinguish "+:=" from "+=:"
and I don't think we have that issue in Ada (though I don't know what "+=:"
meant!).

****************************************************************

From: Robert Dewar
Sent: Tuesday, November 3, 2009  6:43 AM

Nor me, totally unfamiliar, are you sure this was in Algol68

****************************************************************

From: Tucker Taft
Sent: Tuesday, November 3, 2009  7:37 AM

Here is a hand-drawn Algol 68 syntax chart from an old ACM Communications.  It
shows both "<op>:=" and "<op>=:" (I think!):

    http://www.sofport.com:5055/ARG/algol-68-p39-peck.pdf

****************************************************************

From: Robert Dewar
Sent: Tuesday, November 3, 2009  10:53 AM

Well the date suggests it may be preliminary, and I sure don't remember the
other form, what would it mean? I may just have forgotten of course

****************************************************************

From: Robert Dewar
Sent: Tuesday, November 3, 2009  11:10 AM

Anyway, never mind what A68 had, I
prefer +:= because it makes it clear
it is still an assignment, just as
in C += is still clearly an assignment.

****************************************************************

From: Gary Dismukes
Sent: Tuesday, November 3, 2009  12:20 PM

Looking at an Algol 68 textbook I have, it appears that the notation is only
available for use as an alternative to +:= for character strings.  It's called
the "plusto" operator, and "h +=: r" is equivalent to "r +:= h", where r is of
mode "ref string" and h is of mode string or char.

****************************************************************

From: Brad Moore
Sent: Tuesday, November 3, 2009  12:30 PM

This is somewhat related to assignment shorthand, along the lines of improved
notation possibilities... (I apologize if this is too far off topic, if there is
any interest we can create a separate thread)

It would be nice if we could optionally use infix notation more generally for
boolean binary functions, instead of just operators.

e.g. Instead of

if Contains (Grocery_List, Radishes)
if Less_Than (X, Y)
if Is_Factor (3, 21) ... -- Is what a factor of what?

Being able to write

if Grocery_List Contains Radishes
if X Is_Less_Than Y
if 3 Factors_Into 21

Seems more natural.

We do have a reasonable approximation with object prefix notation,
but that only works for tagged types.
eg.
if Grocery_List.Contains(Radishes)

But if one doesn't have a tagged type, you are stuck with prefix notation,
unless you can overload an operator.

Would there be any interest in this capability?

****************************************************************

From: Robert Dewar
Sent: Tuesday, November 3, 2009  12:57 PM

> Being able to write
>
> if Grocery_List Contains Radishes
> if X Is_Less_Than Y
> if 3 Factors_Into 21

This really should be a completely separate topic, it has nothing to do with an
assignment short hand.

Personally I don't like it, and it has huge implementation consequences (it
breaks the invariant that two identifiers cannot appear in sequence).

...
> Would there be any interest in this capability?

It's an interesting language capability (have a look at ABC for a fully
developed version), but to me it does not fit well with Ada syntax.

****************************************************************

From: Brad Moore
Sent: Tuesday, November 3, 2009  2:09 PM

OK, but maybe this does tie in with assignment short hand afterall.
Suppose we said that an infix call had to be enclosed by <>.

As in,

  if 3 <Factors_Into> 21

This would address your concern about two identifiers appearing in sequence, and
would help make it clearer that an infix notation is being used.

Now suppose we extend this idea to also apply to binary procedure calls, in
particular where the first formal is an in out parameter.

Now suppose we added some predefined procedures for elementary types, eg.

procedure "+" (Sum : in out Integer; Addend : Integer);

Then we might be able to write using infix notation;

X <+> 3;  -- Equivalent to "+"(X, 3) or X := X + 3; or in C, X += 3;

This gives us a shorthand notation and gets around having to worry about the
assignment operator, because it is not an assignment. It is a procedure call.

I realize these ideas are a bit "out there", but maybe they will lead to
something...

****************************************************************

From: Bob Duff
Sent: Tuesday, November 3, 2009  3:41 PM

...
> Would there be any interest in this capability?

I might consider something like that in a from-scratch language design, but I
don't think it's appropriate at this point in the life of Ada to be adding such
bells and whistles.

> As in,
>
>   if 3 <Factors_Into> 21

I don't think that works.  It would cause trouble for parsers, since "3
<Factors_Into" is a legal expression.

****************************************************************

From: Bob Duff
Sent: Tuesday, November 3, 2009  3:53 PM

> I'll suggest a new
> compound delimiter <<>> as a strawman, formed by sticking the existing
> left and right label brackets together.

> Is there any interest in considering this proposal?  If so, I can take
> care of drafting the AI.

Like Randy, I have mild interest.  It seems trivial to implement, and somewhat
useful.

I think the "right" way to do it is to have a reserved word (perhaps "idem").
But we certainly don't want to tolerate upward compatibilities for this little
feature, so I agree with your choice of <<>>.

I don't like the += or +:= ideas, because they only work for operators.
The problem we're trying to solve is having to repeat the left-hand side of an
assignment on the right-hand side, which cause trouble because you have to
carefully compare the two, and because you have to worry about side effects.
Both of these:

    Table_Of_Gizmos(Current_Gizmo_Index).Blah_Blah := <<>> + 1;
    Table_Of_Gizmos(Current_Gizmo_Index).Line := Next_Link (<<>>);

seem equally useful.

<<>> should not reevaluate -- the side effects of the lhs should happen once.

I see Tucker's point that the += syntax is familiar to programmers of the C
family of languages.  Good point, but I still don't like it.  Anyway, for Ada to
be readable, you have to learn the language.  E.g.

    select
        ...
        or
            terminate;

Sure, "terminate" is a nice English word, but you can't really understand it
without learning what it means in Ada.

****************************************************************

From: Gary Dismukes
Sent: Tuesday, November 3, 2009  3:31 PM

Here's a skeleton AI for the assignment shorthand proposal, in case it's
possible to add this to the agenda for the upcoming ARG meeting.  Since there
are two suggested approaches for such a feature, further discussion is needed,
so I've mentioned both and not pursued writing up a detailed proposal.

[Editor's note: this is version /01 of the AI.]

****************************************************************

From: Edmond Schonberg
Sent: Tuesday, November 3, 2009  3:42 PM

> r using a more general
> approach that would work for other forms of expression, by adding a
> new form of primary that would stand for the left-hand side.  The
> latter alternative would permit arbitrary use of the target object's
> name on the assignment's right-hand side (e.g., Target_Object := Func
> (T_O)).

Maybe the digraph <- could be used for this purpose:

A.B := F (<-,  <-);

A (X) := <- + 1;

intuitively it hints at its purpose by pointing to the left-hand side in the
assignment.

****************************************************************

From: Stephen Michell
Sent: Tuesday, November 3, 2009  6:23 PM

But I would say the same about +=, not worth the change to Ada.

****************************************************************

From: Robert Dewar
Sent: Tuesday, November 3, 2009  7:34 PM

Well I must say that

    X (A, B, G + 1) := X (A, B, G + 1) + 1;

is pretty ugly, and the Ada way of getting around this is awfully heavy
(declare block, now if we could just say in functional style something like

    J := J + 1 where J = X (A, B, G + 1)

that would be better (please don't think of this as a language suggestion :-))

So to me

   X (A, B, G + 1) +:= 1;

is worthwhile, and trivial to learn, use and implement.

I am dubious about the more general forms with <<>> or whatever ...

****************************************************************

From: Bob Duff
Sent: Tuesday, November 3, 2009  7:48 PM

I'm primarily concerned with implementation difficulty at this point.
Implementers are having trouble keeping up.  Up to Ada 2005, even, and
now we're talking about Ada 2012 or 2015 or whatever it's called.

The "+=" thing is trivial to implement, as is the <<>> thing, whereas
"if Grocery_List Contains Radishes" is probably not.

But having said that, I could easily be convinced that none of this is
worth the trouble!

****************************************************************

From: Bob Duff
Sent: Tuesday, November 3, 2009  7:54 PM

> Maybe the digraph <- could be used for this purpose:

I like it!

In a from-scratch language design, I'd prefer a keyword.
How about the pronoun "it", as in "X[f(i)].Y := it + 1;"?
But as I said, I'm opposed to new reserved words for this purpose.

I can tolerate new reserved words, but only for something important.

****************************************************************

From: Robert Dewar
Sent: Tuesday, November 3, 2009  8:06 PM

I still find this klunky compared to

     X[f(i)].Y +:= 1;

To me this notation takes care of the most common cases.

Note by the way that the example

     BLABLA := Next (BLABLA);

is more easily handled (as in the GNAT sources), by just introducing an
abstraction:

     Next (BLABLA);

which reads just fine, and indeed reads better than

     BLABLA := Next (<-);

or

     BLABLA := Next (it);

Whereas in the +:= case we are
comparing

     A +:= N;

with

     Increment (A, N);   (if we use procedural abstraction)

or

     A := <- + N;        (if we introduce a general
     A := it + N;           language gizmo)

and the +:= notation is better

After all the whole business of infix operators is redundant, we can
write:

    "+" (1, 2);

but we know that we want the +, because in this particular case, the
functional notation is klunky.

Much the same considerations apply to +:= and that's why it is
reasonable to have a special case for infix operators in this situation.

You don't want to generalize if the generalization has a negative effect
on the 99% common use case, and helps only the remaining 1%.

****************************************************************

From: Randy Brukardt
Sent: Tuesday, November 3, 2009  8:32 PM

But that argues for *only* supporting +:= and forgetting the rest of the
operators. None of the other cases are at all likely. And in any case,
we aren't going to support all of the operators in this form:

    **:= is ugly

but the operators that are reserved words don't work at all. I surely
hope we aren't going to allow stuff like:

    mod:=
    and:=

and so on. Those aren't possible to lex in any reasonable way, and parsing
doesn't have enough information (it doesn't see whitespace) to check the
difference between "and:=" and "and :=".

So, no matter what we do, we're going to have a very warty design if you
just try to support this in assignment.

I'm sympathetic to the concern about usability, but I really don't want to
see an amazingly inconsistent design in Ada.

****************************************************************

From: Edmond Schonberg
Sent: Tuesday, November 3, 2009  8:33 PM

I was thinking about it, (I mean "it")  but like you I don't think this small
convenience deserves a new keyword. Maybe we should limit ourselves to op:= 
syntax for the predefined binary operators, and not try to generalize this
to the power of lambda expressions!

****************************************************************

From: Tucker Taft
Sent: Tuesday, November 3, 2009  8:54 PM

It would be simplest to parse "<op>:="
as two separate tokens, and allow white
space between the operator and the ":="
if that is what the user chooses to write.

It doesn't seem so bad to write:

   A(I) mod := 7;

to mean

   A(I) := A(I) mod 7;

In some ways, it almost seems more elegant to
write:

    B(Z) + := 3;

than to jam the two symbols together into "+:=".

****************************************************************

Questions? Ask the ACAA Technical Agent