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