## digitalmars.D - NoNo for Associativity of Assignments?

• Manfred Nowak (22/22) Feb 22 2007 Now that the associativity of comparisons has been dropped, I have
• Joel C. Salomon (14/37) Feb 24 2007 To my mind this means that in the expression
• Manfred Nowak (13/15) Feb 24 2007 Are you sure?
• Joel C. Salomon (6/24) Feb 25 2007 In C-like languages, assignment is right-associative; a = b = c /always/...
• Manfred Nowak (11/13) Feb 25 2007 I have already posted what the specs for D say about evaluation order:
• Stewart Gordon (21/28) Feb 26 2007
Manfred Nowak <svv1999 hotmail.com> writes:
```Now that the associativity of comparisons has been dropped, I have
the heart to point the readers attention to the associativity of
assignments:

There is no evaluation order specified for assignments.

From the specs:
| The right operand is implicitly converted to the type of the left
| operand, and assigned to it. The result type is the type of the
| lvalue, and the result value is the value of the lvalue after the
| assignment.
| The left operand must be an lvalue.

and

| It is an error to depend on order of evaluation when it is not
| specified.

This means: "a = b = c;" is an error unless "a == b" and "b == c"!

But if both conditions hold "a = b = c;" is illegal:

| Expressions that have no effect, like (x + x), are illegal in
| expression statements.

Canonical solutions for this dilemma:
- drop associativity
- specify evaluation order

-manfred

```
Feb 22 2007
"Joel C. Salomon" <JoelCSalomon Gmail.com> writes:
```Manfred Nowak wrote:
Now that the associativity of comparisons has been dropped, I have
the heart to point the readers attention to the associativity of
assignments:

There is no evaluation order specified for assignments.

From the specs:
| The right operand is implicitly converted to the type of the left
| operand, and assigned to it. The result type is the type of the
| lvalue, and the result value is the value of the lvalue after the
| assignment.
| The left operand must be an lvalue.

and

| It is an error to depend on order of evaluation when it is not
| specified.

This means: "a = b = c;" is an error unless "a == b" and "b == c"!

To my mind this means that in the expression
a[f()] = b[g()] = h[()]
it is unspecified in which order f, g, and h are called; specifically,
a[f()] may be evaluated to an lvalue before either of g or h is called,
or after both, or “something else” and it’s an error to care.  Not sure
where the ambiguity you’re claiming in
a = b = c
can arise.

Canonical solutions for this dilemma:
- drop associativity

Bad idea; unlike the semantics for the comparison operators, the meaning
of chained assignments is unambiguous to compiler and programmer alike.

- specify evaluation order

Again, why does it matter if the lvalue-expression is obtained before or
after the rvalue expression?  The grammar removes any ambiguity.

--Joel
```
Feb 24 2007
Manfred Nowak <svv1999 hotmail.com> writes:
```Joel C. Salomon wrote
the meaning of chained assignments is unambiguous to compiler and
programmer alike.

Are you sure?

int a=1, b=2, c=3;
a = b = c;

With associativity this can virtually be rewritten as both
( a = b ) = c;
or
a = ( b = c);

After "( a = b) = c;" a == 2, b == 3, c == 3.
After "a = ( b = c);" a == 3, b == 3, c == 3.

Of course one can _declare_ this to be unambigouous.

-manfred

```
Feb 24 2007
"Joel C. Salomon" <JoelCSalomon Gmail.com> writes:
```Manfred Nowak wrote:
Joel C. Salomon wrote
the meaning of chained assignments is unambiguous to compiler and
programmer alike.

Are you sure?

int a=1, b=2, c=3;
a = b = c;

With associativity this can virtually be rewritten as both
( a = b ) = c;
or
a = ( b = c);

After "( a = b) = c;" a == 2, b == 3, c == 3.
After "a = ( b = c);" a == 3, b == 3, c == 3.

Of course one can _declare_ this to be unambigouous.

In C-like languages, assignment is right-associative; a = b = c /always/
is parsed as a = (b = c).

Also consider if (a = b) = c is even valid — does the expression (a = b)
yield an lvalue?

--Joel
```
Feb 25 2007
Manfred Nowak <svv1999 hotmail.com> writes:
```Joel C. Salomon wrote

In C-like languages, assignment is right-associative; a = b = c
/always/ is parsed as a = (b = c).

I have already posted what the specs for D say about evaluation order:
no right associativity for assignments is given.

When evaluating "a[ 1] = a[ 2] = ... = a[n]" the compiler is allowed to
choose any assignment "a[ i] = a [i+1]" for some valid i at random
order for evaluation.

The compiler is free to store those assignments in an AA and then loop
in a foreach over those assignments to execute them---or even
distribute them over several cores to be faster.

Of course DMD does not do such currently.

-manfred
```
Feb 25 2007
Stewart Gordon <smjg_1998 yahoo.com> writes:
```Manfred Nowak Wrote:

Now that the associativity of comparisons has been dropped, I have
the heart to point the readers attention to the associativity of
assignments:

<snip>
| It is an error to depend on order of evaluation when it is not
| specified.

This means: "a = b = c;" is an error unless "a == b" and "b == c"!

<snip>

Your reasoning appears to be flawed.

a, b and c have no evaluation to be performed.  The only evaluations are of (b
= c) and of (a = result).  The evaluation order _is_ specified: the result of
(b = c) must be evaluated before it can be assigned to a.

Even if the lvalues do need to be evaluated, you're still not necessarily
relying on evaluation order.

For example, for this:

a[++i] = b[j -= 42] = c;

the evaluation order could be any topological sort of this graph:

++i ----------------> &a[++i] ---------------\
+--> a[++i] = b[j -= 42] = c
j -= 42 --> &b[j -= 42] --> b[j -= 42] = c --/

Nowhere does what happens depend on which topological sort is chosen.  However,
if we instead did

a[++i] = b[i -= 42] = c;

then we have a problem, since the indexes used depend on which is evaluated
first: (++i) or (i -= 42).

OST, I think what you're thinking is that, since the evaluation associativity
of (a + b + c) is specified as unspecified, the same holds for = and other
operators.  The bit I can find is

http://www.digitalmars.com/d/portability.html
"a + b + c
can be evaluated as (a + b) + c, a + (b + c), (a + c) + b, (c + b) + a, etc.
Parentheses control operator precedence, parentheses do not control order of
evaluation."

That is, the spec is effectively making an exception for + to the operator
precedence implied by the grammar.  Unless I've missed it, the spec doesn't
make any exception remotely resembling this for = or other operators.
(Strictly speaking, this isn't actually an exception, rather a possibility for
optimisation.)

Stewart.
```
Feb 26 2007