Order of evaluation for named arguments
Dennis
dkorpel at gmail.com
Thu Apr 3 09:33:30 UTC 2025
On Wednesday, 2 April 2025 at 20:14:48 UTC, Timon Gehr wrote:
> Right. Documenting an inconsistency does not make it
> consistent. Language warts are death by a thousand cuts, they
> conspire together to make the language hostile to users.
While I don't think the breakage argument is particularly strong,
I don't consider this a 'language wart'.
First of all, anyone who designs code to only work when the side
effects in an argument list are executed in a particular order
is, to put in Walter's terms, a 'no hire' for me. I'd consider
the side effects to be unordered just like in C, and D's
'left-to-right' specification is simply a courtesy giving more
consistent behavior across compilers. The same way D initializes
`char` to 0xFF and `float` to nan not to be useful, but just as
something more predictable than garbage memory. (Although I'm not
a fan of this, I wish everything was 0 initialized by default).
> I am also just not a big fan of accident-driven language design
> where compiler bugs are codified into the spec.
Second of all, this is not a right characterization. That
specification was written before named arguments existed, and
never explicitly stated whether the order was relative to the
argument list at the call site or the formal parameter list. It
didn't have to, since they'd always be the same. Updating it to
say something different as a new feature enters the language is
not the same as 'codifying a compiler bug in the spec'.
Now you might say: even if the spec is not precise, clearly it
was always intended that side effects are always executed in
lexical order of the source code. But that brings me to the third
point:
Named arguments were explicitly designed to have equivalent
behavior to struct initializers, so they could supersede them.
And as mentioned before, struct initializers also use the order
of the declaration for side effects. Same for array initializers.
In fact, D is full of syntactic sugar for function calls (UFCS,
property syntax, operator overloading) which in the end is always
equivalent to the de-sugared function call.
```D
import std.stdio: writeln;
struct S {
this(int x) {writeln("S(", x, ")");}
auto opBinaryRight(string op)(T a) => this;
}
struct T {
this(int x) {writeln("T(", x, ")");}
}
void main() {
T(2) * S(1); // equivalent to S(1).opBinaryRight(T(2));
// prints:
// S(1)
// T(2)
}
```
So changing the order of evaluation for named argument would be
inconsistent with everything else in the language.
More information about the Digitalmars-d
mailing list