www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - NoNo for Associativity of Assignments?

reply 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
next sibling parent reply "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
parent reply 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
parent reply "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
parent 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
prev sibling parent 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: 

 | 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"!

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