digitalmars.D - Order of evaluation for named arguments
- Steven Schveighoffer (23/24) Mar 29 In the D spec, the function parameter [section on order of
- monkyyy (5/29) Mar 29 I dont read it as wrong, thats left to right at the callsite;
- Steven Schveighoffer (9/12) Mar 29 No, it's the opposite. It takes the order based on the parameter
- monkyyy (9/23) Mar 29 This is a functional vs impertive distinction; math imagines
- Salih Dincer (8/16) Mar 30 Monkyyy brought up an excellent mathematical point, which adds
- Salih Dincer (6/13) Mar 29 Given these considerations, I think updating the specification is
- Salih Dincer (12/14) Mar 29 Adapting the specification rather than modifying the compiler
- Timon Gehr (2/33) Mar 29 Fixing the compiler is better. Changing the spec is slightly easier.
- Walter Bright (7/8) Mar 30 I suspect this issue came about because it simply wasn't considered when...
- Salih Dincer (28/34) Mar 30 C++ does not support named arguments natively, so there’s no
- Walter Bright (2/2) Mar 30 In principle I agree with you, but on a pragmatic note this will silentl...
- Paul Backus (3/5) Mar 30 It will also silently *fix* existing code that was written under
- Timon Gehr (3/9) Mar 31 I am also just not a big fan of accident-driven language design where
- Walter Bright (6/11) Apr 01 If they didn't realize their code was producing the wrong results before...
- Timon Gehr (10/15) Apr 01 So does keeping existing broken behavior. x)
- Walter Bright (11/19) Apr 02 It all depends on the magnitude of the damage done. There are tradeoffs ...
- Timon Gehr (8/39) Apr 02 Right. Documenting an inconsistency does not make it consistent.
- claptrap (2/7) Apr 02 There's an easy hacky fix. That's the decision making process.
- Dennis (48/53) Apr 03 While I don't think the breakage argument is particularly strong,
- GrimMaple (21/23) Apr 03 ayy lmao
- Ogion (8/19) Apr 03 Some newer languages don’t have increment/decrement expressions.
- matheus (21/32) Apr 03 For me the real risk is here:
- Timon Gehr (14/79) Apr 03 I disagree. It's different from C#/Python/... for _no good reason_. It's...
- Dennis (10/11) Apr 03 That's a fair position, but it changes some key facts.
- Timon Gehr (14/27) Apr 03 I do not really think it is important if the accident is in the named
- Dennis (4/10) Apr 03 I wasn't aware of that commitment, have any implementation
- Timon Gehr (15/26) Apr 03 I only found these so far, unfortunately these do not seem as conclusive...
- Jonathan M Davis (8/14) Apr 03 Part of me thinks that we should have randomized the order of evalutatio...
- Timon Gehr (2/21) Apr 03 This is insane. Just don't allow any non-identifier arguments at that po...
- matheus (28/31) Apr 02 I'm not saying you're wrong but is there any data about this? - I
- Sergey (9/17) Apr 02 I'm not sure there was any estimation..
- Jonathan M Davis (11/13) Mar 30 It might, but most folks don't even realize that named arguments are a t...
- Walter Bright (3/13) Apr 01 It's a good argument, but we really have no idea how much code depends o...
- claptrap (16/37) Apr 01 Will it be more or less vitriol than what you get from all the
- Daniel N (21/27) Mar 30 I think you are overlooking one important detail,
- Salih Dincer (25/28) Mar 30 It's a great perspective, but I don't think it's directly related
- Salih Dincer (10/11) Mar 30 Like I said, there's no relevance/problem here. Because there is
- Ogion (15/34) Apr 01 Same with ArrayInitializer:
- Ogion (4/18) Apr 01 Correction:
- Richard (Rikki) Andrew Cattermole (21/21) Mar 31 I've been thinking about this situation for a few days.
- Salih Dincer (13/19) Mar 31 +1
- claptrap (4/19) Mar 31 Or just require that parameters are always passed in the same
- monkyyy (2/20) Mar 31 Doesnt that make the whole thing meaningless
- claptrap (5/26) Apr 01 I thought the point was to document at call site, ie clarify long
- monkyyy (8/35) Apr 01 Im still waiting on named argument templates disambiguation but
- claptrap (2/8) Apr 01 why is having separate functions for drawLine, drawRect bad?
- Patrick Schluter (4/18) Apr 01 It can happen that you change the order of parameter at the
- claptrap (5/25) Apr 01 It'd still break all call sites that don't use named parameters,
- Steven Schveighoffer (17/19) Apr 01 ```d
- claptrap (3/21) Apr 02 Ok yeah thats a good point.
- Salih Dincer (5/5) Mar 31 In this case, the named arguments will have no meaning. It's such
In the D spec, the function parameter [section on order of evaluation](https://dlang.org/spec/expression.html#order-calls) says:Arguments are evaluated left to right.So a question was raised, what about named arguments, since those might not match the order of parameters? I decided to test: ```d import std.stdio; void foo(int a, int b) { writeln(i"a: $(a), b: $(b)"); } void main() { int x; foo(b: ++x, a: ++x); } ``` According to the spec, this should print "a: 2, b: 1", as the order of evaluation of the expression should go left to right. But the actual printout is "a: 1, b: 2". So the question is, should we modify the spec to reflect this, or would it be better to change the compiler to enforce this left-to-right evaluation rule? -Steve
Mar 29
On Saturday, 29 March 2025 at 18:38:31 UTC, Steven Schveighoffer wrote:In the D spec, the function parameter [section on order of evaluation](https://dlang.org/spec/expression.html#order-calls) says:I dont read it as wrong, thats left to right at the callsite; which if the compiler did extra work to break named arguments changing the order of operations would be anti-featureArguments are evaluated left to right.So a question was raised, what about named arguments, since those might not match the order of parameters? I decided to test: ```d import std.stdio; void foo(int a, int b) { writeln(i"a: $(a), b: $(b)"); } void main() { int x; foo(b: ++x, a: ++x); } ``` According to the spec, this should print "a: 2, b: 1", as the order of evaluation of the expression should go left to right. But the actual printout is "a: 1, b: 2". So the question is, should we modify the spec to reflect this, or would it be better to change the compiler to enforce this left-to-right evaluation rule? -Steve
Mar 29
On Saturday, 29 March 2025 at 18:45:14 UTC, monkyyy wrote:I dont read it as wrong, thats left to right at the callsite; which if the compiler did extra work to break named arguments changing the order of operations would be anti-featureNo, it's the opposite. It takes the order based on the parameter order (at declaration), not the argument order (at the call site). I can agree that properly processing the arguments in written order could be more difficult to process in the compiler. But I don't know for sure. In any case, there is a mismatch between the spec and the implementation. -Steve
Mar 29
On Saturday, 29 March 2025 at 21:25:17 UTC, Steven Schveighoffer wrote:On Saturday, 29 March 2025 at 18:45:14 UTC, monkyyy wrote:This is a functional vs impertive distinction; math imagines arguments being reduced by algerbra and in that world the call site isnt relivent, but for a machine left to right at the call site is just it doing as told in order. And Im not saying extra work as in difficult, I mean it functionally the compiler would need to have extra step or do use more storage to make it *less expressive* then the lazy thing.I dont read it as wrong, thats left to right at the callsite; which if the compiler did extra work to break named arguments changing the order of operations would be anti-featureNo, it's the opposite. It takes the order based on the parameter order (at declaration), not the argument order (at the call site). I can agree that properly processing the arguments in written order could be more difficult to process in the compiler. But I don't know for sure. In any case, there is a mismatch between the spec and the implementation. -Steve
Mar 29
On Saturday, 29 March 2025 at 23:03:27 UTC, monkyyy wrote:This is a functional vs impertive distinction; math imagines arguments being reduced by algerbra and in that world the call site isnt relivent, but for a machine left to right at the call site is just it doing as told in order. And Im not saying extra work as in difficult, I mean it functionally the compiler would need to have extra step or do use more storage to make it *less expressive* then the lazy thing.Monkyyy brought up an excellent mathematical point, which adds significant value to the discussion. While Timon provided a summary of the two possibilities, I believe that, given the mathematical foundations of programming, it would be more productive to build upon Monkyyy's perspective rather than approaching it solely from a pragmatic standpoint. SDB 79
Mar 30
On Saturday, 29 March 2025 at 18:38:31 UTC, Steven Schveighoffer wrote:So the question is, should we modify the spec to reflect this, or would it be better to change the compiler to enforce this left-to-right evaluation rule?Given these considerations, I think updating the specification is the more pragmatic approach. The specification could be amended to state:"Positional arguments are evaluated left to right. Named arguments are evaluated in the order of formal parameter declarations."SDB 79
Mar 29
Adapting the specification rather than modifying the compiler requires less development effort and leaves the current compiler implementation (e.g., DMD, LDC, GDC) intact. On Saturday, 29 March 2025 at 18:38:31 UTC, Steven Schveighoffer wrote:or would it be better to change the compiler to enforce this left-to-right evaluation rule?I changed my mind because qhile positional arguments follow a left-to-right evaluation rule, switching to parameter order for named arguments introduces a duality in the language. This could increase the learning curve and require developers to remember two distinct rules. 🫠 SDB 79
Mar 29
On 3/29/25 19:38, Steven Schveighoffer wrote:In the D spec, the function parameter [section on order of evaluation] (https://dlang.org/spec/expression.html#order-calls) says:Fixing the compiler is better. Changing the spec is slightly easier.Arguments are evaluated left to right.So a question was raised, what about named arguments, since those might not match the order of parameters? I decided to test: ```d import std.stdio; void foo(int a, int b) { writeln(i"a: $(a), b: $(b)"); } void main() { int x; foo(b: ++x, a: ++x); } ``` According to the spec, this should print "a: 2, b: 1", as the order of evaluation of the expression should go left to right. But the actual printout is "a: 1, b: 2". So the question is, should we modify the spec to reflect this, or would it be better to change the compiler to enforce this left-to-right evaluation rule? -Steve
Mar 29
On 3/29/2025 4:00 PM, Timon Gehr wrote:Fixing the compiler is better. Changing the spec is slightly easier.I suspect this issue came about because it simply wasn't considered when adding named parameters, and it just fell out this way. Changing it, though, can silently break existing code which makes people unhappy. I suggest changing the spec. P.S. the reason D has a defined behavior for this is because C/C++ leave it implementation-defined.
Mar 30
On Sunday, 30 March 2025 at 07:00:19 UTC, Walter Bright wrote:I suggest changing the spec. P.S. the reason D has a defined behavior for this is because C/C++ leave it implementation-defined.C++ does not support named arguments natively, so there’s no direct comparison. However, function arguments in C++ have unspecified evaluation order—it is implementation-defined. the function call, not in the order of parameters. ```C using System; class Program { static void Foo(int a, int b) { Console.WriteLine($"a: {a}, b: {b}"); } static void Main() { int x = 0; Foo(b: ++x, a: ++x); } } ```a: 2, b: 1it should enforce left-to-right evaluation at the call site. However, modifying the spec would be the "easier" solution, but that would make D behave unpredictably compared to other languages. Given that Walter Bright tends to avoid complex changes, he will likely suggest updating the spec rather than enforcing left-to-right evaluation. But if D wants to be intuitive and SDB 79
Mar 30
In principle I agree with you, but on a pragmatic note this will silently break existing code.
Mar 30
On Sunday, 30 March 2025 at 17:45:07 UTC, Walter Bright wrote:In principle I agree with you, but on a pragmatic note this will silently break existing code.It will also silently *fix* existing code that was written under the assumption that the spec was correct.
Mar 30
On 3/30/25 23:04, Paul Backus wrote:On Sunday, 30 March 2025 at 17:45:07 UTC, Walter Bright wrote:I am also just not a big fan of accident-driven language design where compiler bugs are codified into the spec.In principle I agree with you, but on a pragmatic note this will silently break existing code.It will also silently *fix* existing code that was written under the assumption that the spec was correct.
Mar 31
On 3/31/2025 7:46 AM, Timon Gehr wrote:On 3/30/25 23:04, Paul Backus wrote:If they didn't realize their code was producing the wrong results before, I don't see how they'd realize it was producing correct results later.It will also silently *fix* existing code that was written under the assumption that the spec was correct.I am also just not a big fan of accident-driven language design where compiler bugs are codified into the spec.Breaking existing code has repeatedly driven people away from D. The difficulty with making this change is there's no way to detect if there is a conflict, unless there's an additional requirement that the arguments be pure.
Apr 01
On 4/1/25 20:58, Walter Bright wrote:So does keeping existing broken behavior. x) Why do cautionary C++ tales apply elsewhere but not here? Anyway, e.g. DIP1000 deprecations are hardly comparable to what this is. The evaluation order used to be _not specified_... The spec plainly allowed for breaking code that depends on evaluation order! There are degrees to things, and tradeoffs. It's not black and white. Some benefits are more important than others, and some drawbacks are less important than others. In the end it is up to you, I just don't understand it.I am also just not a big fan of accident-driven language design where compiler bugs are codified into the spec.Breaking existing code has repeatedly driven people away from D.
Apr 01
On 4/1/2025 4:44 PM, Timon Gehr wrote:Why do cautionary C++ tales apply elsewhere but not here?It all depends on the magnitude of the damage done. There are tradeoffs in everything, nothing is a pure win. D is full of compromises.The evaluation order used to be _not specified_... The spec plainly allowed for breaking code that depends on evaluation order!Right. And that was when we were breaking existing code with every new release. We agreed a year or two ago to not continue doing that.There are degrees to things, and tradeoffs. It's not black and white. Some benefits are more important than others, and some drawbacks are less important than others.Absolutely right. Most of my career is programming with implementation defined evaluation order - it's deeply ingrained in me to not rely on it. Implementation-defined also means inconsistency. But I propose to document the existing behavior, so it is consistent and reliable. Consistency is a valuable characteristic.In the end it is up to you, I just don't understand it.If I may be so bold, I think you do understand it, you just don't agree with it :-)
Apr 02
On 4/2/25 21:57, Walter Bright wrote:On 4/1/2025 4:44 PM, Timon Gehr wrote:That does not rule out fixing bugs, I hope.Why do cautionary C++ tales apply elsewhere but not here?It all depends on the magnitude of the damage done. There are tradeoffs in everything, nothing is a pure win. D is full of compromises.The evaluation order used to be _not specified_... The spec plainly allowed for breaking code that depends on evaluation order!Right. And that was when we were breaking existing code with every new release. We agreed a year or two ago to not continue doing that. ...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.There are degrees to things, and tradeoffs. It's not black and white. Some benefits are more important than others, and some drawbacks are less important than others.Absolutely right. Most of my career is programming with implementation defined evaluation order - it's deeply ingrained in me to not rely on it. Implementation-defined also means inconsistency. But I propose to document the existing behavior, so it is consistent and reliable. Consistency is a valuable characteristic. ...I simply do not understand what goes into the decision-making on this. There does not seem to be any consistent line or standard. It is certainly also true that I do not agree with it.In the end it is up to you, I just don't understand it.If I may be so bold, I think you do understand it, you just don't agree with it :-)
Apr 02
On Wednesday, 2 April 2025 at 20:14:48 UTC, Timon Gehr wrote:On 4/2/25 21:57, Walter Bright wrote:There's an easy hacky fix. That's the decision making process.I simply do not understand what goes into the decision-making on this. There does not seem to be any consistent line or standard.
Apr 02
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.
Apr 03
On Thursday, 3 April 2025 at 09:33:30 UTC, Dennis wrote: On Thursday, 3 April 2025 at 09:33:30 UTC, Dennis wrote:initializes `char` to 0xFF and `float` to nan not to be useful, but just as something more predictableayy lmao As a side note, it's probably wise to issue a warning when someone does 'no hire' stuff anyway, eg this code: ```d int t = 1; auto z = t++ + ++t; ``` Should explicitly state that: ``` Warning: variable `t` is modified several times within one sequence point, consider refactoring. ``` Same goes for named arguments (bonus point - it's the same mechanism and the same warning!) ```d var t = 1; foo(a: t++, b: t++); // Warning: variable `t` is modified several times within one sequence point, consider refactoring ```
Apr 03
On Thursday, 3 April 2025 at 12:40:54 UTC, GrimMaple wrote:As a side note, it's probably wise to issue a warning when someone does 'no hire' stuff anyway, eg this code: ```d int t = 1; auto z = t++ + ++t; ``` Should explicitly state that: ``` Warning: variable `t` is modified several times within one sequence point, consider refactoring. ```Some newer languages don’t have increment/decrement expressions. These expressions are great for writing “clever” code, and nobody likes reading and debugging “clever” code. And in trivial cases, `i++` is not *that* much better than `i += 1` to justify the additional language complexity and potential for misuse. Maybe we could deprecate them altogether. But I imagine the pushback.
Apr 03
On Thursday, 3 April 2025 at 12:40:54 UTC, GrimMaple wrote:... ```d int t = 1; auto z = t++ + ++t; ``` Should explicitly state that: ``` Warning: variable `t` is modified several times within one sequence point, consider refactoring. ``` ...For me the real risk is here: import std; void foo(int a, int b){ writeln(a+b); } void main(){ int t = 1; t = 1; foo(t++,++t); t = 1; foo(++t,++t); t = 1; foo(t++,t++); } prints: 4 5 3 Yes I know the problem and the convention and even the appealing for some people with this pre / pos increment. But in college I felt the pain for poor people learning and programming for the first time and facing things like this. Matheus.
Apr 03
On 4/3/25 11:33, Dennis wrote:On Wednesday, 2 April 2025 at 20:14:48 UTC, Timon Gehr wrote:incidental language complexity.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). ...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.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-evaluationI 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.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.
Apr 03
On Thursday, 3 April 2025 at 17:08:57 UTC, Timon Gehr wrote:Those are all language warts.That's a fair position, but it changes some key facts. This is no longer about an accident in the implementation of the recently added named arguments being codified in the spec. Instead, it's cementing a de-facto standard from since the beginning of dmd. A bad standard, but it's not trivial to revert it everywhere. Given that we all seem to agree that argument evaluation order is more about convenience than being a key ingredient for correct programs, that should help you understand Walter's decision making.
Apr 03
On 4/3/25 20:28, Dennis wrote:On Thursday, 3 April 2025 at 17:08:57 UTC, Timon Gehr wrote:I do not really think it is important if the accident is in the named argument implementation or in the thing that named arguments have been deliberately implemented to be consistent with. I also do not want to disparage any of the existing implementation efforts, the spec has been a moving target. This is simply about a commitment that had been made on the newsgroup _to change any the existing behavior deviating from left-to-right_ that has had only partial follow-through so far, and is now being walked back in the spec instead of just a simple: "we have not done it yet because it did not seem important enough and we prioritized other things".Those are all language warts.That's a fair position, but it changes some key facts. This is no longer about an accident in the implementation of the recently added named arguments being codified in the spec.Instead, it's cementing a de-facto standard from since the beginning of dmd. A bad standard, but it's not trivial to revert it everywhere. Given that we all seem to agree that argument evaluation order is more about convenience than being a key ingredient for correct programs, that should help you understand Walter's decision making.No. If that is the reason, then why say it is about not breaking code. Anyway, one does not have to commit to doing it oneself or think it is important in order to agree it is a good thing to be done in general.
Apr 03
On Thursday, 3 April 2025 at 18:48:49 UTC, Timon Gehr wrote:This is simply about a commitment that had been made on the newsgroup _to change any the existing behavior deviating from left-to-right_ that has had only partial follow-through so far, and is now being walked back in the spec instead of just a simple: "we have not done it yet because it did not seem important enough and we prioritized other things".I wasn't aware of that commitment, have any implementation changes been made since that? And do you have a link to the newsgroup thread?
Apr 03
On 4/3/25 21:26, Dennis wrote:On Thursday, 3 April 2025 at 18:48:49 UTC, Timon Gehr wrote:I only found these so far, unfortunately these do not seem as conclusive as I remember (because they usually talk specifically about "functions" and I suspect some functions are considered to be more function-like than other functions): TDPL, says function arguments are evaluated left-to-right on page 50. https://forum.dlang.org/thread/f0pvsn$1pju$1 digitalmars.com https://github.com/dlang/dlang.org/pull/6 https://lists.puremagic.com/pipermail/digitalmars-d/2011-December/118189.html https://forum.dlang.org/thread/ylgtwzvqnupnehipxayk forum.dlang.org https://forum.dlang.org/thread/vbpjyhxtjmtebnjmidyf forum.dlang.org AFAIU both my frontend and SDC went with strict source-order evaluation. That seems like the only sensible generalization of left-to-right function argument evaluation, but perhaps common sense is not so common after all.This is simply about a commitment that had been made on the newsgroup _to change any the existing behavior deviating from left-to-right_ that has had only partial follow-through so far, and is now being walked back in the spec instead of just a simple: "we have not done it yet because it did not seem important enough and we prioritized other things".I wasn't aware of that commitment, have any implementation changes been made since that? And do you have a link to the newsgroup thread?
Apr 03
On Thursday, April 3, 2025 3:33:30 AM MDT Dennis via Digitalmars-d wrote: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.Part of me thinks that we should have randomized the order of evalutation with every run of the compiler just to shake out code that relies on it. Having it be defined to be left-to-right certainly helps with consistency, but I completely agree that code shouldn't be relying on it - if nothing else, because it's a bad habit to get into given that there are other major languages which don't follow it. - Jonathan M Davis
Apr 03
On 4/3/25 19:19, Jonathan M Davis wrote:On Thursday, April 3, 2025 3:33:30 AM MDT Dennis via Digitalmars-d wrote:This is insane. Just don't allow any non-identifier arguments at that point.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.Part of me thinks that we should have randomized the order of evalutation with every run of the compiler just to shake out code that relies on it. Having it be defined to be left-to-right certainly helps with consistency, but I completely agree that code shouldn't be relying on it - if nothing else, because it's a bad habit to get into given that there are other major languages which don't follow it. - Jonathan M Davis
Apr 03
On Tuesday, 1 April 2025 at 18:58:08 UTC, Walter Bright wrote:... Breaking existing code has repeatedly driven people away from D. ...I'm not saying you're wrong but is there any data about this? - I mean after "n" breakages we had a decrease in numbers of users? I pretty sure complains about breakages exists, as some developers leaved D community because restraint or DIP bureaucracy, but I think in the end most people would prefer a coherent language than another C++ one. Will users leave because this broke up software or fell safe that it follows a pattern? The problem I see with situation like this, is that we can't complain later when some streamer decide to use a language and show its problems for a large audience, and just after that people start to realize that we should have fixed this earlier. using System; public class Program{ public static int x; public static void foo(int a, int b){ Console.WriteLine("a: " + a + " b: " + b); } public static void Main(){ foo(b:++x,a:++x); } } Prints: a: 2 b: 1 So, arguments are evaluated left to right. Matheus.
Apr 02
On Wednesday, 2 April 2025 at 11:11:24 UTC, matheus wrote:On Tuesday, 1 April 2025 at 18:58:08 UTC, Walter Bright wrote:I'm not sure there was any estimation.. People were pissed off because of breaking tooling/projects every release.. I'm not sure how bad people will feel about breaking once a year with clear suggestions (semi-automatic scripts) of fixing breaking parts Seems not so many complaints in Rust/Zig.. and I think they have more production code than D (even Zig which is not even 1.0)... Breaking existing code has repeatedly driven people away from D. ...I'm not saying you're wrong but is there any data about this? - I mean after "n" breakages we had a decrease in numbers of users?
Apr 02
On Sunday, March 30, 2025 11:45:07 AM MDT Walter Bright via Digitalmars-d wrote:In principle I agree with you, but on a pragmatic note this will silently break existing code.It might, but most folks don't even realize that named arguments are a thing in D, and most code doesn't rely on the order of evaluation of the arguments to a function. As such, I would expect that the amount of code that would actually break would be extremely small (and possibly zero). Most bug fixes risk silently breaking some piece of code that accidentally relied on the broken behavior, and I think this is a case where the odds of it actually causing problems are sufficiently low that it's worth just making it all consistent - and the sooner we do it, the less likely it is to break any code. - Jonathan M Davis
Mar 30
On 3/30/2025 6:21 PM, Jonathan M Davis wrote:It might, but most folks don't even realize that named arguments are a thing in D, and most code doesn't rely on the order of evaluation of the arguments to a function. As such, I would expect that the amount of code that would actually break would be extremely small (and possibly zero). Most bug fixes risk silently breaking some piece of code that accidentally relied on the broken behavior, and I think this is a case where the odds of it actually causing problems are sufficiently low that it's worth just making it all consistent - and the sooner we do it, the less likely it is to break any code.It's a good argument, but we really have no idea how much code depends on named arguments. I'm also really tired of the vitriol we get when breaking existing code.
Apr 01
On Tuesday, 1 April 2025 at 19:00:49 UTC, Walter Bright wrote:On 3/30/2025 6:21 PM, Jonathan M Davis wrote:Will it be more or less vitriol than what you get from all the people who expect the arguments to be evaluated left to right? I mean there seems to be a pretty solid consensus that is what is expected. This fails pretty bad on the principle of least surprise right? And as it is now you have to look up the definition of the function to understand what order the arguments are evaluated. You cant know just by looking at the call code, you need to look at the function definition. It's unnecessary cognitive load, and unintuitive. And you will probably have to listen to people complain about it for years to come, just like the "strict private" crap. You want to have years and years of flame wars over argument evaluation order? Make the hard but correct decision.It might, but most folks don't even realize that named arguments are a thing in D, and most code doesn't rely on the order of evaluation of the arguments to a function. As such, I would expect that the amount of code that would actually break would be extremely small (and possibly zero). Most bug fixes risk silently breaking some piece of code that accidentally relied on the broken behavior, and I think this is a case where the odds of it actually causing problems are sufficiently low that it's worth just making it all consistent - and the sooner we do it, the less likely it is to break any code.It's a good argument, but we really have no idea how much code depends on named arguments. I'm also really tired of the vitriol we get when breaking existing code.
Apr 01
On Saturday, 29 March 2025 at 18:38:31 UTC, Steven Schveighoffer wrote:In the D spec, the function parameter [section on order of evaluation](https://dlang.org/spec/expression.html#order-calls) says:I think you are overlooking one important detail, StructInitializer, it must match named arguments and fortunately it does. ```d import std.stdio; struct S { int a, b; } int fun(int v) { v.writeln; return v; } void main() { S r; S s = { b:fun(1), a:fun(2) }; } ``` 2 1Arguments are evaluated left to right.So a question was raised, what about named arguments, since those might not match the order of parameters?
Mar 30
On Sunday, 30 March 2025 at 09:14:49 UTC, Daniel N wrote:I think you are overlooking one important detail, StructInitializer, it must match named arguments and fortunately it does.It's a great perspective, but I don't think it's directly related to our topic. I've tried to increase the value below, but I haven't been successful in establishing relevance. 😇 ```d auto inc(T)(ref T value) { scope(exit) value.writeln; return ++value; } struct S { int a, b; } import std.stdio; void main() { auto x = 41; x.writeln; S s = { b : inc(x), a : inc(x) }; s.writeln; } ``` SDB 79
Mar 30
On Sunday, 30 March 2025 at 09:40:10 UTC, Salih Dincer wrote:...I don't think it's directly related to our topic...Like I said, there's no relevance/problem here. Because there is no ordering from the right or the left. The compiler selects and initials it according to the order in the struct. ```d enum fun = (int v) => v; S r = { b:fun(1), a:fun(2) }; r.writeln; // S(2, 1) ``` SDB 79
Mar 30
On Sunday, 30 March 2025 at 09:14:49 UTC, Daniel N wrote:I think you are overlooking one important detail, StructInitializer, it must match named arguments and fortunately it does. ```d import std.stdio; struct S { int a, b; } int fun(int v) { v.writeln; return v; } void main() { S r; S s = { b:fun(1), a:fun(2) }; } ``` 2 1Same with ArrayInitializer: ```D import std.stdio; int fun(int v) { v.writeln; return v; } void main() { int[2] a = [ 1:fun(1), 0:fun(2) ]; } ``` 1 2
Apr 01
On Tuesday, 1 April 2025 at 09:05:59 UTC, Ogion wrote:Same with ArrayInitializer: ```D import std.stdio; int fun(int v) { v.writeln; return v; } void main() { int[2] a = [ 1:fun(1), 0:fun(2) ]; } ``` 1 2Correction: 2 1
Apr 01
I've been thinking about this situation for a few days. I recognize that changing the compiler may not be a simple task. My conclusion about the specification is that an attempt was made to define D so that the order of evaluation is always as written left to right. See comma expression for a near identical evaluation definition. Before named arguments were added, the arguments list and parameter list orders matched, so a poorly written description was accurate. However with named arguments the distinction between a called function parameter list dictating the matched argument list order, and the order as written by the user argument list, became meaningful. It is my view that the order of evaluation should mirror that of the programmer, or at least be predictable. Named arguments entirely eliminate this predictability as a possibility as the order of evaluation could change over time or be in any position "unknown" to the user. Right now the order in which arguments are written do not contribute to evaluation ordering. Although I suspect that this is more of an oversight then what is intended. Regardless the spec here needs some work done to make this clearer, because it is confusing the called functions definition against the arguments list.
Mar 31
On Monday, 31 March 2025 at 19:47:01 UTC, Richard (Rikki) Andrew Cattermole wrote:It is my view that the order of evaluation should mirror that of the programmer, or at least be predictable. Named arguments entirely eliminate this predictability as a possibility as the order of evaluation could change over time or be in any position "unknown" to the user.+1 If the probability is low, as Jonathan emphasizes, then please change the behavior of the D compiler. Or if not, in this case, here is the intermediate solution: **Add a warning or error message** "Named arguments are evaluated in parameter order, so be mindful of side effects!" If this behavior is intentional, it at least needs to be clearly communicated. In summary, we cannot get away with changing the specification. Because this is an unintuitive situation. SDB 79
Mar 31
On Monday, 31 March 2025 at 21:43:07 UTC, Salih Dincer wrote:On Monday, 31 March 2025 at 19:47:01 UTC, Richard (Rikki) Andrew Cattermole wrote:Or just require that parameters are always passed in the same order as the declaration. Makes this bug impossible, and no *silent* breakage.It is my view that the order of evaluation should mirror that of the programmer, or at least be predictable. Named arguments entirely eliminate this predictability as a possibility as the order of evaluation could change over time or be in any position "unknown" to the user.+1 If the probability is low, as Jonathan emphasizes, then please change the behavior of the D compiler. Or if not, in this case, here is the intermediate solution: **Add a warning or error message** "Named arguments are evaluated in parameter order, so be mindful of side effects!"
Mar 31
On Monday, 31 March 2025 at 23:16:57 UTC, claptrap wrote:On Monday, 31 March 2025 at 21:43:07 UTC, Salih Dincer wrote:Doesnt that make the whole thing meaninglessOn Monday, 31 March 2025 at 19:47:01 UTC, Richard (Rikki) Andrew Cattermole wrote:Or just require that parameters are always passed in the same order as the declaration. Makes this bug impossible, and no *silent* breakage.[...]+1 If the probability is low, as Jonathan emphasizes, then please change the behavior of the D compiler. Or if not, in this case, here is the intermediate solution: **Add a warning or error message** "Named arguments are evaluated in parameter order, so be mindful of side effects!"
Mar 31
On Tuesday, 1 April 2025 at 02:04:44 UTC, monkyyy wrote:On Monday, 31 March 2025 at 23:16:57 UTC, claptrap wrote:I thought the point was to document at call site, ie clarify long parameter lists, and enable skipping defaults? I mean I don't see the point of just being able to change the order the parameters are passed in?On Monday, 31 March 2025 at 21:43:07 UTC, Salih Dincer wrote:Doesnt that make the whole thing meaninglessOn Monday, 31 March 2025 at 19:47:01 UTC, Richard (Rikki) Andrew Cattermole wrote:Or just require that parameters are always passed in the same order as the declaration. Makes this bug impossible, and no *silent* breakage.[...]+1 If the probability is low, as Jonathan emphasizes, then please change the behavior of the D compiler. Or if not, in this case, here is the intermediate solution: **Add a warning or error message** "Named arguments are evaluated in parameter order, so be mindful of side effects!"
Apr 01
On Tuesday, 1 April 2025 at 11:26:34 UTC, claptrap wrote:On Tuesday, 1 April 2025 at 02:04:44 UTC, monkyyy wrote:Im still waiting on named argument templates disambiguation but im worried about expressiveness For example raylib has like 20 draw functions in a c verbose style; it be nice to overload them all; but oh no draw line and draw rectangle overlap (4 arguments, two x's and y's) in thoery after named argument works with templates you can redirect via parsing the .h defination easilyOn Monday, 31 March 2025 at 23:16:57 UTC, claptrap wrote:I thought the point was to document at call site, ie clarify long parameter lists, and enable skipping defaults? I mean I don't see the point of just being able to change the order the parameters are passed in?On Monday, 31 March 2025 at 21:43:07 UTC, Salih Dincer wrote:Doesnt that make the whole thing meaninglessOn Monday, 31 March 2025 at 19:47:01 UTC, Richard (Rikki) Andrew Cattermole wrote:Or just require that parameters are always passed in the same order as the declaration. Makes this bug impossible, and no *silent* breakage.[...]+1 If the probability is low, as Jonathan emphasizes, then please change the behavior of the D compiler. Or if not, in this case, here is the intermediate solution: **Add a warning or error message** "Named arguments are evaluated in parameter order, so be mindful of side effects!"
Apr 01
On Tuesday, 1 April 2025 at 12:04:36 UTC, monkyyy wrote:On Tuesday, 1 April 2025 at 11:26:34 UTC, claptrap wrote: Im still waiting on named argument templates disambiguation but im worried about expressiveness For example raylib has like 20 draw functions in a c verbose style; it be nice to overload them all; but oh no draw line and draw rectangle overlap (4 arguments, two x's and y's)why is having separate functions for drawLine, drawRect bad?
Apr 01
On Tuesday, 1 April 2025 at 11:26:34 UTC, claptrap wrote:On Tuesday, 1 April 2025 at 02:04:44 UTC, monkyyy wrote:It can happen that you change the order of parameter at the definition site. This should not require modiying all call sites with named arguments.On Monday, 31 March 2025 at 23:16:57 UTC, claptrap wrote:I thought the point was to document at call site, ie clarify long parameter lists, and enable skipping defaults? I mean I don't see the point of just being able to change the order the parameters are passed in?On Monday, 31 March 2025 at 21:43:07 UTC, Salih Dincer wrote:Doesnt that make the whole thing meaningless[...]Or just require that parameters are always passed in the same order as the declaration. Makes this bug impossible, and no *silent* breakage.
Apr 01
On Tuesday, 1 April 2025 at 17:13:45 UTC, Patrick Schluter wrote:On Tuesday, 1 April 2025 at 11:26:34 UTC, claptrap wrote:It'd still break all call sites that don't use named parameters, maybe even silently if you're not careful. So its a thin argument IMO, changing the order of the parameters just seems like a bad idea, its just breakage, for nothing.On Tuesday, 1 April 2025 at 02:04:44 UTC, monkyyy wrote:It can happen that you change the order of parameter at the definition site. This should not require modiying all call sites with named arguments.On Monday, 31 March 2025 at 23:16:57 UTC, claptrap wrote:I thought the point was to document at call site, ie clarify long parameter lists, and enable skipping defaults? I mean I don't see the point of just being able to change the order the parameters are passed in?On Monday, 31 March 2025 at 21:43:07 UTC, Salih Dincer wrote:Doesnt that make the whole thing meaningless[...]Or just require that parameters are always passed in the same order as the declaration. Makes this bug impossible, and no *silent* breakage.
Apr 01
On Tuesday, 1 April 2025 at 11:26:34 UTC, claptrap wrote:I mean I don't see the point of just being able to change the order the parameters are passed in?```d int generateNextThing(); // assume this is not easy to replicate void foo(int a, int b); void main() { // I want to pass the next thing in as b, and the next next thing in as a. auto bval = generateNextThing(); foo(generateNextThing(), bval); // hey, why not just pass them in the order specified! foo(b: generateNextThing(), a: generateNextThing()); // oops next thing goes to a, next next thing goes to b. } ``` It's not exactly a killer example, but you can see how one might expect that to work as the spec details. -Steve
Apr 01
On Wednesday, 2 April 2025 at 02:09:40 UTC, Steven Schveighoffer wrote:On Tuesday, 1 April 2025 at 11:26:34 UTC, claptrap wrote:Ok yeah thats a good point.I mean I don't see the point of just being able to change the order the parameters are passed in?```d int generateNextThing(); // assume this is not easy to replicate void foo(int a, int b); void main() { // I want to pass the next thing in as b, and the next next thing in as a. auto bval = generateNextThing(); foo(generateNextThing(), bval); // hey, why not just pass them in the order specified! foo(b: generateNextThing(), a: generateNextThing()); // oops next thing goes to a, next next thing goes to b. } ``` It's not exactly a killer example, but you can see how one might expect that to work as the spec details.
Apr 02
In this case, the named arguments will have no meaning. It's such a thing that it sets you free; when you assign arguments default values. In the past, this facility did not exist and I used to feel very stuck. SDB 79
Mar 31