(I discuss such topics here because I don't know where else I can)
I have seen a recent change:
http://dsource.org/projects/dmd/changeset/399
I guess it's something related to specifying an evaluation order in D in
function calls like bar() of main():
import std.stdio: writeln;
import std.string: format;
class Obj {
int x;
this(int xx) { x = xx; }
string member() { return format("member ", x); }
}
Obj foo() {
return new Obj(2);
}
void bar(string s, Obj o2) {
writeln("bar ", s, " ", o2.x);
}
void main() {
Obj o = new Obj(1);
bar(o.member(), o=foo());
}
C specifications do not define the order of evaluation for function arguments.
It can be left-to-right, right-to-left or anything else and is unspecified.
Thus any code which relies on this order of evaluation is not portable.
D can solve this problem as I think Java has done, just specifying it, and
forcing the compiler to produce hypothetically a bit less efficient code in
some situations.
Another strategy to solve this problem that's possible in D (and not possible
in C) is to allow only pure expressions inside function calls. So in a function
call you can put pure expressions like x+5 or calls to pure functions. And then
the D compiler is free to leave unspecified the order of evaluation of function
arguments.
Bye,
bearophile

C specifications do not define the order of evaluation for function
arguments. It can be left-to-right, right-to-left or anything else and is
unspecified. Thus any code which relies on this order of evaluation is not
portable.
D can solve this problem as I think Java has done, just specifying it, and
forcing the compiler to produce hypothetically a bit less efficient code
in some situations.
Another strategy to solve this problem that's possible in D (and not
possible in C) is to allow only pure expressions inside function calls. So
in a function call you can put pure expressions like x+5 or calls to pure
functions. And then the D compiler is free to leave unspecified the order
of evaluation of function arguments.

I would prefer that the evaluation order be officially specified as
non-deterministic. That is, the standard guarantees that the observable
behavior be equivalent to some sequential order of evaluation.
For example:
void f() {}
f(x = 1, x = 2);
assert(x == 1 || x == 2);
It's the same as what C does, just more formally defined. The compiler is
free to choose the most efficient implementation that satisfies the
contract.
This is because to me, any asymmetric choice of evaluation order would be
arbitrary and wrong. What's so special about left-to-right?
--
Michiel Helvensteijn

All compiler behavior is based on what the observer sees. If the
compiler can rearrange things in a manner that the observer cannot
detect, then the rearrangement is allowed.

OK. But if the language turns putting impure expressions inside a function call
into a compile time error, allowing only pure expressions inside function
calls, then the compiler can always be free to rearrange those expressions, and
there's both no performance penalty and the programmer can be certain there is
no performance penalty. I guess you are not interested in this idea.
Bye,
bearophile

All compiler behavior is based on what the observer sees. If the
compiler can rearrange things in a manner that the observer cannot
detect, then the rearrangement is allowed.

OK. But if the language turns putting impure expressions inside a
function call into a compile time error, allowing only pure
expressions inside function calls, then the compiler can always be
free to rearrange those expressions, and there's both no performance
penalty and the programmer can be certain there is no performance
penalty. I guess you are not interested in this idea.

I agree I'm not interested in making impure expressions illegal.
But I was just pointing out that the compiler optimizer *already* relies
on knowing about side effects when reordering code. It's central to any
flow analysis optimization.

This is because to me, any asymmetric choice of evaluation order would be
arbitrary and wrong. What's so special about left-to-right?

Arbitrary, yes. Wrong? no - specifying it removes another source of
potential user bugs. Left-to-right is natural because that's the way we
read things.

I'm sure you are aware that entire cultures read things right-to-left.
Anyway, don't think I don't see your reasoning. I can argue your point:
* Even though both are equally well-defined behavioral contracts, many
people will understand a fixed sequential order better than
non-deterministic choice, so might cause more bugs in the latter case.
* D already contains English keywords and English libraries. It's already
dominantly western, so left-to-right won't be unexpected.
I just have this quest for a beautiful and elegant programming language. In
such a language, the order of side-effects should not matter in any
operation (not just function calls).
Operators that are commutative in math (and, or, +, *) should be commutative
in the programming language too, regardless of side-effects and
short-circuiting (which would still be possible, ask me how).
But I understand why D places more value on practicality than beauty and
elegance.
--
Michiel Helvensteijn