Order of evaluation for named arguments
Timon Gehr
timon.gehr at gmx.ch
Thu Apr 3 17:08:57 UTC 2025
On 4/3/25 11:33, Dennis wrote:
> 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'.
> ...
I disagree. It's different from C#/Python/... for _no good reason_. It's
incidental language complexity.
> 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).
> ...
Therefore the breakage argument is really weak. Anyway, there are use
cases where evaluating in source order is just more convenient for
inspection e.g. logging.
>> 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.
Yes, I am indeed saying that. At least that was what we had discussed on
the newsgroup and what I had implemented in my frontend before the spec
was updated with this abomination:
https://dlang.org/spec/expression.html#order-of-evaluation
> 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.
Which is bad.
> Same for array initializers.
Which is bad.
> 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.
Those are all language warts. So is the fact that for AssignExpression
the order is still implementation-defined.
More information about the Digitalmars-d
mailing list