www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP 1030--Named Arguments--Community Review Round 1 Discussion

reply Mike Parker <aldacron gmail.com> writes:
This is the feedback thread for the first round of Community 
Review for DIP 1030, "Named Arguments":

https://github.com/dlang/DIPs/blob/44b0d4ec0da6a2e797ede748fb1e81cd6db10371/DIPs/DIP1030.md

Here in the discussion thread, you are free to discuss anything 
and everything related to the DIP. Express your support or 
opposition, debate alternatives, argue the merits... in other 
words, business as usual.

However, if you have any specific feedback for how to improve the 
the proposal itself, then please post it in the feedback thread. 
The feedback thread will be the source for the review summary I 
write at the end of this review round. I will post a link to that 
thread immediately following this post. Just be sure to read and 
understand the Reviewer Guidelines before posting there:

https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

The review period will end at 11:59 PM ET on February 20, or when 
I make a post declaring it complete. Discussion in this thread 
may continue beyond that point.

At the end of Round 1, if further review is deemed necessary, the 
DIP will be scheduled for another round of Community Review. 
Otherwise, it will be queued for the Final Review and Formal 
Assessment.

Please stay on topic here. I will delete posts that are 
completely off topic.
Feb 05
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Thursday, 6 February 2020 at 06:08:59 UTC, Mike Parker wrote:

 However, if you have any specific feedback for how to improve 
 the the proposal itself, then please post it in the feedback 
 thread.
The feedback thread is here: https://forum.dlang.org/post/bizqhxszbobynrimsgai forum.dlang.org
Feb 05
prev sibling next sibling parent reply Andrea Fontana <nospam example.com> writes:
On Thursday, 6 February 2020 at 06:08:59 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Community 
 Review for DIP 1030, "Named Arguments":
What about UFSC + named arguments? Andrea
Feb 06
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/6/20 4:39 AM, Andrea Fontana wrote:
 On Thursday, 6 February 2020 at 06:08:59 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Community Review 
 for DIP 1030, "Named Arguments":
What about UFSC + named arguments?
Responding to this and the one in the feedback thread. My understanding is that UFCS works like this: a.foo(...); translates to: foo(a, ...); So if you follow that logic, the rules apply after that translation as if you called the function that way. example: void doStuff(int a, string b, double c) {} 3.doStuff(6.7, b: "ham") => doStuff(3, 6.7, b: ham) => error, no match (6.7 doesn't match type to b) 3.doStuff(c: 6.7, b: "ham") => doStuff(3, c: 6.7, b: ham) => OK, all parameters match 3.doStuff(a: 5, "ham", 6.7) => doStuff(3, a: 5, "ham", 6.7) => error, cannot match a twice Might be a good point to add UFCS discussion to the DIP. -Steve
Feb 06
next sibling parent reply Andrea Fontana <nospam example.com> writes:
On Thursday, 6 February 2020 at 15:30:40 UTC, Steven 
Schveighoffer wrote:
 On 2/6/20 4:39 AM, Andrea Fontana wrote:
 Might be a good point to add UFCS discussion to the DIP.

 -Steve
I wonder whether or not "(c: 3).doStuff(3,4);" could be useful... Probably it just adds some noise.
Feb 06
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Feb 06, 2020 at 05:03:06PM +0000, Andrea Fontana via Digitalmars-d
wrote:
 On Thursday, 6 February 2020 at 15:30:40 UTC, Steven Schveighoffer wrote:
 On 2/6/20 4:39 AM, Andrea Fontana wrote:
 Might be a good point to add UFCS discussion to the DIP.
[...]
 I wonder whether or not "(c: 3).doStuff(3,4);" could be useful...
 Probably it just adds some noise.
IMO it not only adds noise, it opens the door for expanding UFCS far beyond its original charter. Because now, nothing stops you from doing this: struct A {} struct B {} struct C {} auto fun(A a, B b, C c) { ... } A a; B b; C c; (a: a).fun(b: b, c: c); (b: b).fun(a: a, c: c); (c: c).fun(a: a, b: b); IOW, you can now pull out any arbitrary parameter from any function and do UFCS on it. I honestly don't think this is a good idea, as it will open up whole cans o' worms esp. once it starts interacting with IFTI. T -- We are in class, we are supposed to be learning, we have a teacher... Is it too much that I expect him to teach me??? -- RL
Feb 06
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Thursday, 6 February 2020 at 17:03:06 UTC, Andrea Fontana 
wrote:
 On Thursday, 6 February 2020 at 15:30:40 UTC, Steven 
 Schveighoffer wrote:
 On 2/6/20 4:39 AM, Andrea Fontana wrote:
 Might be a good point to add UFCS discussion to the DIP.

 -Steve
I wonder whether or not "(c: 3).doStuff(3,4);" could be useful... Probably it just adds some noise.
Remmeber, UFCS is only tried when property lookup fails. Since `(c: 3).doStuff` is not a valid property access, it cannot possibly be a valid UFCS call.
Feb 06
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/6/2020 7:30 AM, Steven Schveighoffer wrote:
 Might be a good point to add UFCS discussion to the DIP.
Your analysis is correct and inevitable and doesn't need discussion in the DIP. It's another illustration why lowering is a good idea - it takes care of things like this renderubg further exposition and design work not necessary.
Feb 06
prev sibling next sibling parent reply Lim <himeix outlook.com> writes:
On Thursday, 6 February 2020 at 06:08:59 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Community 
 Review for DIP 1030, "Named Arguments"
How about template arguments? Can we still omit the parentheses if it is one token long? i.e., template Example(int a = 0, alias b, int c = 0) => Example!b:1 If the answer is yes, considering the following code: template SomeTemplate(int a = 0, alias b, int c = 0) { alias SomeTemplate = b; } const b = 2; const c = 3; switch(someInt) { case 1: .. case SomeTemplate!b : c: writeln("we are in case"); break; default: writeln("we are in default"); goto c; } It's valid now and when someInt >= 3, "we are in default" and "we are in case" will both be printed. According to the rule "If an Identifier is present, it matches the Parameter with the corresponding Identifier", when this DIP come into power, this code won't compile as there is no LabeledStatement Identifier named c. Is this a potential compatibility issue? Or is there a misunderstanding of my interpretation of the new DIP?
Feb 06
next sibling parent Lim <himeix outlook.com> writes:
On Thursday, 6 February 2020 at 21:06:38 UTC, Lim wrote:
 template SomeTemplate(int a = 0, alias b, int c = 0)
Should be: template SomeTemplate(alias b, int c = 0)
Feb 06
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/6/20 4:06 PM, Lim wrote:
 On Thursday, 6 February 2020 at 06:08:59 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Community Review 
 for DIP 1030, "Named Arguments"
How about template arguments? Can we still omit the parentheses if it is one token long? i.e., template Example(int a = 0, alias b, int c = 0) => Example!b:1
I think this is ambiguous: template Example(int b) { enum Example = b + 5; } enum b = 5; auto x = true ? Example!b:1; or maybe: case Example!b: It could be worked out if one examines the whole expression/statement, but I think we're better off avoiding support for such things. Note that existing templates don't allow operators when omitting parentheses. -Steve
Feb 06
next sibling parent reply Lim <himeix outlook.com> writes:
On Thursday, 6 February 2020 at 21:37:11 UTC, Steven 
Schveighoffer wrote:
 It could be worked out if one examines the whole 
 expression/statement, but I think we're better off avoiding 
 support for such things.

 Note that existing templates don't allow operators when 
 omitting parentheses.

 -Steve
Yep, that's what I mean. We should make it impossible or have a predictable behavior. Unfortunately, this case was not mentioned in DIP 1030.
Feb 06
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/6/20 4:46 PM, Lim wrote:
 On Thursday, 6 February 2020 at 21:37:11 UTC, Steven Schveighoffer wrote:
 It could be worked out if one examines the whole expression/statement, 
 but I think we're better off avoiding support for such things.

 Note that existing templates don't allow operators when omitting 
 parentheses.
Yep, that's what I mean. We should make it impossible or have a predictable behavior. Unfortunately, this case was not mentioned in DIP 1030.
I'm not sure it needs mentioning, as long as we are going to continue to enforce the current rules (no operators are included unless you use parentheses). Allowing colons as part of the no-parentheses template arg would be a difference that required a grammar change. As the DIP isn't changing that grammar (it's here: https://dlang.org/spec/grammar.html#TemplateSingleArgument), we shouldn't need to discuss it. -Steve
Feb 06
parent Lim <himeix outlook.com> writes:
On Thursday, 6 February 2020 at 21:58:19 UTC, Steven 
Schveighoffer wrote:
 https://dlang.org/spec/grammar.html#TemplateSingleArgument), we 
 shouldn't need to discuss it.
I'm sold.
Feb 06
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/6/2020 1:37 PM, Steven Schveighoffer wrote:
 It could be worked out if one examines the whole expression/statement, but I 
 think we're better off avoiding support for such things.
Note that C++ stepped into a similar mess when picking < > for template arguments. We're not going that way.
Feb 06
prev sibling parent reply Lim <himeix outlook.com> writes:
On Thursday, 6 February 2020 at 21:06:38 UTC, Lim wrote:
 Can we still omit the parentheses if it is one token long?
And another example of this issue: template Example(alias x, int y = 0) { ... } // assume x defined before is(Example!x : int) { ... } Note: Although DIP 88 and DIP 1020 give some examples on using Named Arguments with single parameter template (all with parentheses). Nothing is mentioned on whether parentheses are required in this situation. According to current Spec: "If the TemplateArgument is one token long, the parentheses can be omitted", all two examples I showed are legal. As the indentifier tokens are not the same thing as TemplateArgument tokens: +TemplateNamedArgument: + Identifier : TemplateArgument + TemplateArgument Thus, the single-token parameter use case should be regulated in DIP 1030.
Feb 06
parent Dennis <dkorpel gmail.com> writes:
On Thursday, 6 February 2020 at 21:41:33 UTC, Lim wrote:
 According to current Spec: "If the TemplateArgument is one 
 token long, the parentheses can be omitted", all two examples I 
 showed are legal.
One token, not one argument. `a:b` and alike are three tokens long. See https://dlang.org/spec/lex.html#tokens
Feb 06
prev sibling next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, February 5, 2020 11:08:59 PM MST Mike Parker via Digitalmars-d 
wrote:
 This is the feedback thread for the first round of Community
 Review for DIP 1030, "Named Arguments":

 https://github.com/dlang/DIPs/blob/44b0d4ec0da6a2e797ede748fb1e81cd6db1037
 1/DIPs/DIP1030.md

 Here in the discussion thread, you are free to discuss anything
 and everything related to the DIP. Express your support or
 opposition, debate alternatives, argue the merits... in other
 words, business as usual.

 However, if you have any specific feedback for how to improve the
 the proposal itself, then please post it in the feedback thread.
 The feedback thread will be the source for the review summary I
 write at the end of this review round. I will post a link to that
 thread immediately following this post. Just be sure to read and
 understand the Reviewer Guidelines before posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 The review period will end at 11:59 PM ET on February 20, or when
 I make a post declaring it complete. Discussion in this thread
 may continue beyond that point.

 At the end of Round 1, if further review is deemed necessary, the
 DIP will be scheduled for another round of Community Review.
 Otherwise, it will be queued for the Final Review and Formal
 Assessment.

 Please stay on topic here. I will delete posts that are
 completely off topic.
Well, I'll say again that I don't like the idea of having named arguments in the language, because it makes the parameter names part of the API, resulting in yet more bikeshedding and yet another thing that can't be changed without breaking existing code. Once in a while, named arguments may be useful, but for the most part, they're useful because a function has way too many parameters, in which case, the function should have been designed differently. Unfortunately, since it's Walter who created the DIP, and a number of people do like the idea of named arguments, I expect that some form of this will make it in, but I still think that it's a bad idea. - Jonathan M Davis
Feb 06
next sibling parent reply Piotrek <unknown dummyaddress.org> writes:
On Friday, 7 February 2020 at 03:33:26 UTC, Jonathan M Davis 
wrote:
[...]
 Well, I'll say again that I don't like the idea of having named 
 arguments in the language, because it makes the parameter names 
 part of the API, resulting in yet more bikeshedding and yet 
 another thing that can't be changed without breaking existing 
 code.
For me, the DIP is on the top of the improvements list. I missed it many times. I found the code with named arguments much more readable no mater how many arguments are defined for the functions (i.e. including those with even 1 argument in some cases). Regarding API design. To some extent the names of arguments are already a part of API in any programming language. They form a documentation for users which can be referenced in many places. As for the "breaking change" problem. My opinion is that there should be an appropriate deprecation process available for any change in the language without an exception. Surly it needs some planning and rationale which is costly, making it not straightforward and not applicable in some cases. But the "braking change" problem shouldn't be an unbreakable barrier for improvements which are worth it. Additionally DIPs have trial period, don't they? Piotrek
Feb 07
parent bachmeier <no spam.net> writes:
On Friday, 7 February 2020 at 17:06:21 UTC, Piotrek wrote:

 Regarding API design. To some extent the names of arguments are 
 already a part of API in any programming language. They form a 
 documentation for users which can be referenced in many places.
This has been discussed many times already, but a big problem with named arguments is that it creates a lot of overhead when writing new functions. Rather than worrying about what the functionality is supposed to do, you have to think of argument names that are good for the long run.* That's a whole lot of overhead. * Of course, you can come back to it "in the future" after you have your library finished and tested. Nobody in the history of programming has ever done that.
Feb 07
prev sibling next sibling parent reply matheus <matheus gmail.com> writes:
On Friday, 7 February 2020 at 03:33:26 UTC, Jonathan M Davis 
wrote:
 Well, I'll say again that I don't like the idea of having named 
 arguments in the language, because it makes the parameter names 
 part of the API, resulting in yet more bikeshedding and yet 
 another thing that can't be changed without breaking existing 
 code. Once in a while, named arguments may be useful, but for 
 the most part, they're useful because a function has way too 
 many parameters, in which case, the function should have been 
 designed differently.
Like you said: "...named arguments may be useful, but for the most part, they're useful because a function has way too many parameters, the function should have been designed differently.". Matheus.
Feb 07
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Feb 07, 2020 at 07:02:14PM +0000, matheus via Digitalmars-d wrote:
 On Friday, 7 February 2020 at 03:33:26 UTC, Jonathan M Davis wrote:
 Well, I'll say again that I don't like the idea of having named
 arguments in the language, because it makes the parameter names part
 of the API, resulting in yet more bikeshedding and yet another thing
 that can't be changed without breaking existing code. Once in a
 while, named arguments may be useful, but for the most part, they're
 useful because a function has way too many parameters, in which
 case, the function should have been designed differently.
Like you said: "...named arguments may be useful, but for the most part, they're useful because a function has way too many parameters, the function should have been designed differently.".
[...] I agree that this tends to be the use case, and I agree that when the number of function parameters exceed a certain threshold, it should be designed differently. At the very least, the parameters should be factored into a struct that can then be initialized by the caller and passed in as a whole, rather than isolated arguments. However, I *have* also found myself desiring nameable arguments for the sake of self-documenting code, for example: myRange.process(nRetries: 2); as opposed to: myRange.process(2); // what does '2' mean?! I can't say this is always desirable, but there are situations where it would be nice, maybe because the parameter is optional, or tangential to the function's main purpose, so it's not immediately obvious what it does. There are definitely times when I'd say this is a sign of bad API design, but I also can't say that 100% of the time. As with all things, there are exceptions, and in the exceptional cases named arguments can be just the thing to fill that need. T -- It's bad luck to be superstitious. -- YHL
Feb 07
parent reply matheus <matheus gmail.com> writes:
On Friday, 7 February 2020 at 19:26:10 UTC, H. S. Teoh wrote:
 ...
 However, I *have* also found myself desiring nameable arguments 
 for the sake of self-documenting code, for example:

 	myRange.process(nRetries: 2);

 as opposed to:

 	myRange.process(2); // what does '2' mean?!
 ...
Yes this is one case that people will argue in favor of named arguments, but on the other hand I would point out: Why is he using a magic number in a code? :) A define/enum/variable would fix this issue, at least in most documentations I read I usually see variables to explain the "expected parameters". Another thing is current Editors/IDE help with this problem too, they show what parameters a function is expected even the overloads while you typing. https://docs.microsoft.com/en-us/dotnet/api/system.dayofweek?view=netframework-4.8#examples You will see a example of DateTime usage like this:
 // Assume the current culture is en-US.
 // Create a DateTime for the first of May, 2003.
    DateTime dt = new DateTime(2003, 5, 1);
They didn't even bother to use named arguments there. They just warned about culture en-US. :) Well in my opinion I would prefer to see development in other areas than in this particular case. Matheus.
Feb 07
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Feb 07, 2020 at 07:59:41PM +0000, matheus via Digitalmars-d wrote:
 On Friday, 7 February 2020 at 19:26:10 UTC, H. S. Teoh wrote:
 ...
 However, I *have* also found myself desiring nameable arguments for
 the sake of self-documenting code, for example:
 
 	myRange.process(nRetries: 2);
 
 as opposed to:
 
 	myRange.process(2); // what does '2' mean?!
 ...
Yes this is one case that people will argue in favor of named arguments, but on the other hand I would point out: Why is he using a magic number in a code? :)
<rant> IMNSHO, the obsession with getting rid of magic numbers is a bunch of hooey. There's a time and place for that, e.g., you don't want two pieces of code to go out of sync when the constants they use must match a common value. But pushing this to the extremes leads to stupid code like this: enum two = 2; // look, ma! I know how to name magic numbers! myRange.process(two); // yay, no more magic numbers! which is completely ridiculous. If the constant only appears in one place, just write the damn constant out already, that's why the programming language has integer literals, dammit. Giving it a name just because "magic numbers are Bad(tm)" is stupid. </rant> [...]
 https://docs.microsoft.com/en-us/dotnet/api/system.dayofweek?view=netframework-4.8#examples
 
 You will see a example of DateTime usage like this:
 
 // Assume the current culture is en-US.
 // Create a DateTime for the first of May, 2003.
    DateTime dt = new DateTime(2003, 5, 1);
They didn't even bother to use named arguments there. They just warned about culture en-US. :)
Actually, that's not en-US. In *true* American style, the correct order of arguments should be (5, 1, 2003). :-P (Which IMNSHO is a stupid, illogical convention, which gets especially bad when they drop the first 2 digits of the year, and then you get incomprehensible dates like 10/12/11: is it Oct 12, 2011? Dec 10, 2011? Or Dec 11, 2010? Or maybe Nov 12, 2010? Who even knows. Everyone should just stick with ISO-style yyyy-mm-dd, dangit!!)
 Well in my opinion I would prefer to see development in other areas
 than in this particular case.
[...] True, Walter himself has said D needs to have a small number of powerful tools that are very expressive, rather than be a kitchen sink full of every feature you can think of but each is anemic and more-or-less redundant. T -- Do not reason with the unreasonable; you lose by definition.
Feb 07
parent reply matheus <matheus gmail.com> writes:
On Friday, 7 February 2020 at 21:57:18 UTC, H. S. Teoh wrote:
 On Fri, Feb 07, 2020 at 07:59:41PM +0000, matheus via 
 Digitalmars-d wrote:
 On Friday, 7 February 2020 at 19:26:10 UTC, H. S. Teoh wrote:
 ...
 However, I *have* also found myself desiring nameable 
 arguments for
 the sake of self-documenting code, for example:
 
 	myRange.process(nRetries: 2);
 
 as opposed to:
 
 	myRange.process(2); // what does '2' mean?!
 ...
Yes this is one case that people will argue in favor of named arguments, but on the other hand I would point out: Why is he using a magic number in a code? :)
<rant> IMNSHO, the obsession with getting rid of magic numbers is a bunch of hooey. There's a time and place for that, e.g., you don't want two pieces of code to go out of sync when the constants they use must match a common value. But pushing this to the extremes leads to stupid code like this: enum two = 2; // look, ma! I know how to name magic numbers! myRange.process(two); // yay, no more magic numbers! which is completely ridiculous. ...
Hold your rant buddy I was just replying to your example :)
 	myRange.process(2); // what does '2' mean?!
But of course seeing a code like:
 	enum two = 2; // look, ma! I know how to name magic numbers!
 	myRange.process(two); // yay, no more magic numbers!
Would be totally nonsense to me too. On the other hand:
 	myRange.process(nRetries);
For me would be ok and a standard where I work. And the IDE would give me the hint about the value of nRetries. Talking about magic numbers, well I had enough of it after diving into code like[1]:
 tempy = 0x80000000;
 for(i=-131072;i<=131072;i+=(2048>>gride))
 plc = x1+mulscale12((2047-y1)&4095,inc);
 i = ((y1+2048)>>12); daend = ((y2+2048)>>12);
And need to understand each number. :) Matheus. [1] - https://github.com/videogamepreservation/dukenukem3d/blob/master/SRC/ENGINE.C
Feb 07
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Feb 07, 2020 at 10:28:27PM +0000, matheus via Digitalmars-d wrote:
[...]
 Hold your rant buddy I was just replying to your example :)
I know. But you struck a nerve. ;-)
 	myRange.process(2); // what does '2' mean?!
But of course seeing a code like:
 	enum two = 2; // look, ma! I know how to name magic numbers!
 	myRange.process(two); // yay, no more magic numbers!
Would be totally nonsense to me too. On the other hand:
 	myRange.process(nRetries);
For me would be ok and a standard where I work. And the IDE would give me the hint about the value of nRetries.
Fair enough. But it seems a bit onerous to have to write this: int nRetries = 2; myRange.process(nRetries); when you could just write: myRange.process(nRetries: 2);
 Talking about magic numbers, well I had enough of it after diving into
 code like[1]:
 
 tempy = 0x80000000;
 for(i=-131072;i<=131072;i+=(2048>>gride))
 plc = x1+mulscale12((2047-y1)&4095,inc);
 i = ((y1+2048)>>12); daend = ((y2+2048)>>12);
And need to understand each number. :)
I see nonsense like this all the time. It's common practice in "enterprise" code. It's one of the red flags that says "don't touch this spaghetti code unless you can eat the consequences". My policy is to stay away from such code unless you absolutely can't get out of touching it. And even then, touch as little as you can to get your job done, and then get outta there pronto, before the fragile tower of cards that is the code comes crashing down on your head. :-P In this particular case, clearly the constants aren't just one-off constants; they have a specific meaning and really should be refactored into named constants instead. So in this case, I'd say it's a *good* thing to get rid of the magic numbers. But I disagree with the hardline attitude of "there must be no integer literals in your code outside of constant declarations", which is apparently what some people actually believe. In each case, a judgment call must be made, and there is no one-size-fits-all answer. As Walter said once: I've been around long enough to have seen an endless parade of magic new techniques du jour, most of which purport to remove the necessity of thought about your programming problem. In the end they wind up contributing one or two pieces to the collective wisdom, and fade away in the rearview mirror. You cannot just take a rule of thumb like "avoid magic constants" as a crutch to avoid the necessity of thought about your present programming problem. Sometimes it makes sense, but sometimes it doesn't; it doesn't make any sense to have a knee-jerk reaction "aaaaah, magic constant!" every time you see a naked integer literal. T -- Obviously, some things aren't very obvious.
Feb 07
prev sibling parent reply bachmeier <no spam.net> writes:
On Friday, 7 February 2020 at 19:02:14 UTC, matheus wrote:

 "...named arguments may be useful, but for the most part, 
 they're useful because a function has way too many parameters, 
 the function should have been designed differently.".
It actively encourages a style of "just add another function argument". You start small and as you decide to change your function, it's easy to fall into the trap of adding one more argument, because the end user is free to ignore it.
Feb 07
parent Paul Backus <snarwin gmail.com> writes:
On Friday, 7 February 2020 at 19:44:31 UTC, bachmeier wrote:
 On Friday, 7 February 2020 at 19:02:14 UTC, matheus wrote:

 "...named arguments may be useful, but for the most part, 
 they're useful because a function has way too many parameters, 
 the function should have been designed differently.".
It actively encourages a style of "just add another function argument". You start small and as you decide to change your function, it's easy to fall into the trap of adding one more argument, because the end user is free to ignore it.
People will do this anyway, whether or not the language has named arguments. In fact, here are a couple examples in D where it's been done in the past: - https://github.com/dlang/dmd/pull/8195 - https://github.com/dlang/druntime/pull/2376 At least with named arguments, I have the option of writing `destroy!(initialize: false)(foo)`, instead of just `destroy!false(foo)`.
Feb 07
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/6/2020 7:33 PM, Jonathan M Davis wrote:
 Well, I'll say again that I don't like the idea of having named arguments in
 the language, because it makes the parameter names part of the API,
 resulting in yet more bikeshedding and yet another thing that can't be
 changed without breaking existing code. Once in a while, named arguments may
 be useful, but for the most part, they're useful because a function has way
 too many parameters, in which case, the function should have been designed
 differently.
 
 Unfortunately, since it's Walter who created the DIP, and a number of people
 do like the idea of named arguments, I expect that some form of this will
 make it in, but I still think that it's a bad idea.
I appreciate your thoughts on this. But I like the feature even if all it does is make the "Flag" template obsolete: https://dlang.org/library/std/typecons/flag.html So instead of: foo(Yes.caseSensitive) we'd write: foo(caseSensitive : true) There's no overhead or cognitive load of an extra type, and it doesn't look stupid.
Feb 07
next sibling parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Saturday, 8 February 2020 at 03:57:56 UTC, Walter Bright wrote:
 On 2/6/2020 7:33 PM, Jonathan M Davis wrote:
 Well, I'll say again that I don't like the idea of having 
 named arguments in
 the language, because it makes the parameter names part of the 
 API,
 resulting in yet more bikeshedding and yet another thing that 
 can't be
 changed without breaking existing code. Once in a while, named 
 arguments may
 be useful, but for the most part, they're useful because a 
 function has way
 too many parameters, in which case, the function should have 
 been designed
 differently.
 
 Unfortunately, since it's Walter who created the DIP, and a 
 number of people
 do like the idea of named arguments, I expect that some form 
 of this will
 make it in, but I still think that it's a bad idea.
I appreciate your thoughts on this. But I like the feature even if all it does is make the "Flag" template obsolete: https://dlang.org/library/std/typecons/flag.html So instead of: foo(Yes.caseSensitive) we'd write: foo(caseSensitive : true) There's no overhead or cognitive load of an extra type, and it doesn't look stupid.
Honestly, I like the Flag template ... I think Jonathan have nailed the point:. In my little, I've a PR waiting for months as it breaks a possible derived class of Phobos Socket, as none is marking methods 'final' when it's not intended to be part of the API. And that remember me that, once alone a time, you and Andrei agreed that turning the default to 'final' from 'virtual' was the correct thing to do, specifically for the above point: the default should encourage the writing of a "minimalist" API boundary. Now, I'm all with Jonathan on that, having the parameters name part of the API is just going in the wrong direction related to the above: we are enlarging the possibility of code breakage. Do we want to go further down that road?
Feb 08
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/8/2020 12:42 AM, Paolo Invernizzi wrote:
 Now, I'm all with Jonathan on that, having the parameters name part of the API 
 is just going in the wrong direction related to the above: we are enlarging
the 
 possibility of code breakage. Do we want to go further down that road?
This PR would discourage gratuitous name changes of parameters, just like changing the name of a function causes breakage. The problem is easily avoided - don't change the parameter names. It's not the same thing as changing the behavior.
Feb 08
prev sibling parent FeepingCreature <feepingcreature gmail.com> writes:
On Saturday, 8 February 2020 at 08:42:57 UTC, Paolo Invernizzi 
wrote:
 I think Jonathan have nailed the point:. In my little, I've a 
 PR waiting for months as it breaks a possible derived class of 
 Phobos Socket, as none is marking methods 'final' when it's not 
 intended to be part of the API. And that remember me that, once 
 alone a time, you and Andrei agreed that turning the default to 
 'final' from 'virtual' was the correct thing to do, 
 specifically for the above point: the default should encourage 
 the writing of a "minimalist" API boundary.
I'm sorry, I need to hammer this in. A nameless API is not minimal. An API is not made more minimal by ignoring the names! The *meaning* of parameters is part of the API! If you have a function DateTime(1, 2, 3), then you already have a function DateTime that takes day, month and year, whether or not you have named parameters! The only difference is that the *meanings* "day", "month" and "year", which are part of the API in either case(!), are attached to the *positions* of the parameters. So now the *positions* of parameters are an irreducible part of the public API. And frankly to me that's a lot worse than having the names being part of it. Names you can at least remember sometimes. Positions are fully arbitrary. Named parameters are just the API being honest about the meaning it *already* carries in its specification, instead of hiding it behind meaningless numbers.
Feb 08
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, February 7, 2020 8:57:56 PM MST Walter Bright via Digitalmars-d 
wrote:
 On 2/6/2020 7:33 PM, Jonathan M Davis wrote:
 Well, I'll say again that I don't like the idea of having named
 arguments in the language, because it makes the parameter names part of
 the API, resulting in yet more bikeshedding and yet another thing that
 can't be changed without breaking existing code. Once in a while, named
 arguments may be useful, but for the most part, they're useful because
 a function has way too many parameters, in which case, the function
 should have been designed differently.

 Unfortunately, since it's Walter who created the DIP, and a number of
 people do like the idea of named arguments, I expect that some form of
 this will make it in, but I still think that it's a bad idea.
I appreciate your thoughts on this. But I like the feature even if all it does is make the "Flag" template obsolete: https://dlang.org/library/std/typecons/flag.html So instead of: foo(Yes.caseSensitive) we'd write: foo(caseSensitive : true) There's no overhead or cognitive load of an extra type, and it doesn't look stupid.
That is an upside to it, though I don't think that it's worth having to deal with named arguments in general just get rid of Flag. I confess though that I've always thought that Flag was an unnecessary complication and have only used it because people have been insisting that it's best practice. I never use it in code that isn't in a library that I'm writing for other people to use. If you're familiar with the function, then a naked bool is enough to understand what the function call is doing and no sort of argument name at the call site is necessary. If you aren't familiar with the function, then you should be reading its documentation anyway instead of assuming that you understand what it does based simply on what it's called or what the names of its arguments are. And in that sense, named arguments seem to me like a further excuse to try to claim that you don't need to actually read the documentation to understand what functions do, which ultimately leads to shooting yourself in the foot when you make an assumption that doesn't match the assumptions that the function's author made. - Jonathan M Davis
Feb 11
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Wednesday, 12 February 2020 at 05:03:49 UTC, Jonathan M Davis 
wrote:
 If you're familiar with the function, then a naked bool is 
 enough to understand what the function call is doing and no 
 sort of argument name at the call site is necessary. If you 
 aren't familiar with the function, then you should be reading 
 its documentation anyway instead of assuming that you 
 understand what it does based simply on what it's called or 
 what the names of its arguments are.
This strikes me as a false dichotomy, in two ways. 1) It's entirely possible to be familiar enough with a function to understand what it does, but not so familiar that you have every detail of its parameter list memorized. For example, if I see `stdin.byLine(true)`, I may remember that the boolean argument has to do with whether it keeps or drops newlines, but not be sure which behavior `true` corresponds to. `stdin.byLine(keepTerminator: true)` makes it immediately obvious. 2) While function and argument names certainly communicate *less* information than documentation does, the amount they communicate is not zero. For example, if I'm reading some code in an unfamiliar language, and I see something like `Math.abs(x)`, I have a pretty good idea what that means even without looking at the documentation, because the name refers to an existing piece of background knowledge I possess. Names can't tell you everything, of course. If you need to know more, you can (and should) refer to the documentation, or failing that, the source code. But sometimes, you don't need to know everything, and in those situations, being able to get what you need from names is far more convenient than having to search the documentation every time.
Feb 11
prev sibling parent reply aliak <something something.com> writes:
On Wednesday, 12 February 2020 at 05:03:49 UTC, Jonathan M Davis 
wrote:
 On Friday, February 7, 2020 8:57:56 PM MST Walter Bright via 
 Digitalmars-d wrote:
 On 2/6/2020 7:33 PM, Jonathan M Davis wrote:
 Well, I'll say again that I don't like the idea of having 
 named arguments in the language, because it makes the 
 parameter names part of the API, resulting in yet more 
 bikeshedding and yet another thing that can't be changed 
 without breaking existing code. Once in a while, named 
 arguments may be useful, but for the most part, they're 
 useful because a function has way too many parameters, in 
 which case, the function should have been designed 
 differently.

 Unfortunately, since it's Walter who created the DIP, and a 
 number of people do like the idea of named arguments, I 
 expect that some form of this will make it in, but I still 
 think that it's a bad idea.
I appreciate your thoughts on this. But I like the feature even if all it does is make the "Flag" template obsolete: https://dlang.org/library/std/typecons/flag.html So instead of: foo(Yes.caseSensitive) we'd write: foo(caseSensitive : true) There's no overhead or cognitive load of an extra type, and it doesn't look stupid.
That is an upside to it, though I don't think that it's worth having to deal with named arguments in general just get rid of Flag. I confess though that I've always thought that Flag was an unnecessary complication and have only used it because people have been insisting that it's best practice. I never use it in code that isn't in a library that I'm writing for other people to use. If you're familiar with the function, then a naked bool is enough to understand what the function call is doing and no sort of argument name at the call site is necessary. If you aren't familiar with the function, then you should be reading its documentation anyway instead of assuming that you understand what it does based simply on what it's called or what the names of its arguments are. And in that sense, named arguments seem to me like a further excuse to try to claim that you don't need to actually read the documentation to understand what functions do, which ultimately leads to shooting yourself in the foot when you make an assumption that doesn't match the assumptions that the function's author made.
Named arguments is the difference between spending 1 second looking at this: makeWindow(x: 67, y: 98, width: 100, height: 100) Or taking about 1 to 5 minutes depending on how easy documentation is to find, and how bored you are to figure out what this is doing: makeWindow(67, 98, 100, 100) The 1 to 5 minutes is guesstimate work. But there's a lot of research out there about human task behavior. E.g. you have about 2-3 minutes of someone's attention before you switch tasks. It can take anywhere from a minute to 20 to get back to what you were doing after a context switch. Looking up and searching for documentation unnecessarily is most certainly a context switch. Add the fact that many libraries do not have documentation or poor documentation, that means browsing the source code. Throw in attention spans and anything you can do to make code readable/reviewable is a huge win to productivity. Unless you're a lone programmer working on your own project consistently this doesn't apply. But even then if you switch between projects it does, because there's no way you're remember what every bool or int parameter does. Coding in the professional world is mostly social. The languages that make it more social and help that aspect will win the long game.
 - Jonathan M Davis
Feb 11
next sibling parent reply SashaGreat <s g.com> writes:
On Wednesday, 12 February 2020 at 07:42:32 UTC, aliak wrote:
 Named arguments is the difference between spending 1 second 
 looking at this:

 makeWindow(x: 67, y: 98, width: 100, height: 100)

 Or taking about 1 to 5 minutes depending on how easy 
 documentation is to find, and how bored you are to figure out 
 what this is doing:

 makeWindow(67, 98, 100, 100)
You're using an example in favor of a point, because it's hard to someone use constants for this kind of thing for a production code, at least for obvious reasons it shouldn't. Now let's compare:
 makeWindow(x: 67, y: 98, width: 100, height: 100)
With: makeWindow(x, y, width, height); Of course 'x', 'y', 'width' and 'height' are variables defined elsewhere, but it's less noisy. Now to be honest I would prefer for this particular function to use a struct like "myWindow" to define the coordinates: makeWindow(myWindow); I barely use name parameters for languages that support and to be honest I barely see than in other codes. IDE are pretty much advanced these days, and if I need to check out at least in VS it shows me everything that I need about the arguments (Names, Types...). Sasha.
Feb 12
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/12/20 2:44 PM, SashaGreat wrote:
 On Wednesday, 12 February 2020 at 07:42:32 UTC, aliak wrote:
 Named arguments is the difference between spending 1 second looking at 
 this:

 makeWindow(x: 67, y: 98, width: 100, height: 100)

 Or taking about 1 to 5 minutes depending on how easy documentation is 
 to find, and how bored you are to figure out what this is doing:

 makeWindow(67, 98, 100, 100)
You're using an example in favor of a point, because it's hard to someone use constants for this kind of thing for a production code, at least for obvious reasons it shouldn't. Now let's compare:
 makeWindow(x: 67, y: 98, width: 100, height: 100)
With: makeWindow(x, y, width, height); Of course 'x', 'y', 'width' and 'height' are variables defined elsewhere, but it's less noisy.
I agree with you! But it depends on the situation. I'll embelish with something else. Let's say that you have variables for some and you want to put in literals for others, which do you prefer? makeWindow(67, 98, width, height) or makeWindow(x: 67, y: 98, width, height) You see, you can use named parameters when it makes sense, and not when it doesn't. I think this is really just a greater mechanism to make calls more self-documenting, and code much easier to read and understand.
 Now to be honest I would prefer for this particular function to use a 
 struct like "myWindow" to define the coordinates:
 
 makeWindow(myWindow);
This is just named parameters with extra types needed. Same as the Flag case. Removing all that cruft from the library and language is a net-win. And it doesn't help when you want to use expressions to generate new parameters -- the code is going to be ugly because you first have to construct a typeof(myWindow).
 I barely use name parameters for languages that support and to be honest 
 I barely see than in other codes.
My second most used language is Swift, which requires named parameters. There are some cool things you can do with function and parameter names when they are significant. I think it's going to be a net benefit. We just have to resolve the introspection issue. -Steve
Feb 12
parent reply Sasha <s g.com> writes:
On Wednesday, 12 February 2020 at 20:11:14 UTC, Steven 
Schveighoffer wrote:
 My second most used language is Swift, which requires named 
 parameters. There are some cool things you can do with function 
 and parameter names when they are significant. I think it's 
 going to be a net benefit. We just have to resolve the 
 introspection issue.
Since I never used named arguments, I mean I never opted to and since you have, can you share about the problems, because it must have some problems, changing the names will cause problem, but how this happen in production? Like I said above I'm curious about this feature, and why C/C++ which have a bigger user base never bothered about adding this feature. Sasha.
Feb 12
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Wednesday, 12 February 2020 at 21:53:32 UTC, Sasha wrote:
 Like I said above I'm curious about this feature, and why C/C++ 
 which have a bigger user base never bothered about adding this 
 feature.

 Sasha.
The only official, publicly-available information I could find on this [1] is frustratingly vague, but I did stumble across a reddit thread [2] that discusses some of the potential issues. One is that different implementations of the C and C++ standard libraries can (and do) use different parameter names for the same functions. Unless those names were standardized, any code that called such functions using named arguments would not be portable among different implementations. In D, this is not a problem, because there is only one implementation of Phobos and Druntime, so the names are de-facto standardized already. [1] [2] https://www.reddit.com/r/cpp/comments/5mdes5/what_happened_to_the_named_parameter_proposal/
Feb 12
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/12/20 4:53 PM, Sasha wrote:
 On Wednesday, 12 February 2020 at 20:11:14 UTC, Steven Schveighoffer wrote:
 My second most used language is Swift, which requires named 
 parameters. There are some cool things you can do with function and 
 parameter names when they are significant. I think it's going to be a 
 net benefit. We just have to resolve the introspection issue.
Since I never used named arguments, I mean I never opted to and since you have, can you share about the problems, because it must have some problems, changing the names will cause problem, but how this happen in production?
Swift is notorious for making breaking changes, including function and parameter names (which are technically part of the function name), but provides generally a rich tool in xcode to upgrade your code to deal with the differences. Of course, it's not always perfect. I was pissed when they removed for loops without providing a replacement. But renaming of function names AND parameters is handled quite easily. It is definitely a difference for a language that has had named parameters from the beginning vs. one that suddenly allows that. The mentality is different and the care for parameter names is different. If this DIP is accepted, I expect some growing pains, but it should be pretty much fine pretty quickly IMO.
 Like I said above I'm curious about this feature, and why C/C++ which 
 have a bigger user base never bothered about adding this feature.
There's lots of useful things C/C++ could add that they haven't. The bar to cross for C++ new features is going to be a difficult threshold for any feature, including named parameters, regardless of the utility or benefits. They just don't like to change much. I don't know that I would ascribe some inherent problem with named parameters as the cause of it not being in C++, or really any language. Changing a language always has to be worth it to the maintainers, and opinions on this feature differ widely even here. -Steve
Feb 13
prev sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Wednesday, 12 February 2020 at 19:44:52 UTC, SashaGreat wrote:
 On Wednesday, 12 February 2020 at 07:42:32 UTC, aliak wrote:
 Named arguments is the difference between spending 1 second 
 looking at this:

 makeWindow(x: 67, y: 98, width: 100, height: 100)

 Or taking about 1 to 5 minutes depending on how easy 
 documentation is to find, and how bored you are to figure out 
 what this is doing:

 makeWindow(67, 98, 100, 100)
You're using an example in favor of a point, because it's hard to someone use constants for this kind of thing for a production code, at least for obvious reasons it shouldn't. Now let's compare:
 makeWindow(x: 67, y: 98, width: 100, height: 100)
With: makeWindow(x, y, width, height);
You could use variables to make it look nicer at the call-side, but the downside is there's no guarantee that those variable names have any relation to the names of the parameters. For example, this would still compile: makeWindow(x, width, y, height); This problem can't happen with named arguments. Named arguments also saves you if the function arguments change names/meaning, i.e. ORIGINAL: void makeWindow(int x, int y, int width, int height) MODIFIED: void makeWindow(int left, int top, int right, int bottom); The version that doesn't use named arguments will still compile and run: makeWindow(x, y, width, height); But named arguments would catch the problem at compile-time: makeWindow(x: 67, y: 98, width: 100, height: 100); // error no argument named 'x', 'y', 'width', 'height'
Feb 12
parent reply Sasha <s g.com> writes:
On Wednesday, 12 February 2020 at 21:11:12 UTC, Jonathan Marler 
wrote:
 You could use variables to make it look nicer at the call-side, 
 but the downside is there's no guarantee that those variable 
 names have any relation to the names of the parameters. For 
 example, this would still compile:

 makeWindow(x, width, y, height);

 This problem can't happen with named arguments.  Named 
 arguments also saves you if the function arguments change 
 names/meaning, i.e.

 ORIGINAL: void makeWindow(int x, int y, int width, int height)
 MODIFIED: void makeWindow(int left, int top, int right, int 
 bottom);

 The version that doesn't use named arguments will still compile 
 and run:

 makeWindow(x, y, width, height);

 But named arguments would catch the problem at compile-time:

 makeWindow(x: 67, y: 98, width: 100, height: 100); // error no 
 argument named 'x', 'y', 'width', 'height'
OK, now let's see a problem with named arguments, imagine this: makeWindow(x, y, width, height); You can call this function like: makeWindow(x: 67, y: 98, width: 100, height: 100); // Name Arguments makeWindow(67, 98, 100, 100); // Constants makeWindow(x, y, width, height); // Variables So far so good, but later someone decides to rename some parameters to: makeWindow(posx, posy, width, height); // Note: x => posx and y => posy makeWindow(x: 67, y: 98, width: 100, height: 100); // Ops not working anymore! makeWindow(67, 98, 100, 100); // Constants still works makeWindow(x, y, width, height); // Variables Still works What I mean is that we need to balance this better, you showed a defect without Named Arguments and I'm showing a problem with. But one thing that called my attention is that for what I see C++ doesn't has this feature, and proposes were rejected because the problems that would be created with this feature. Sasha.
Feb 12
next sibling parent JN <666total wp.pl> writes:
On Wednesday, 12 February 2020 at 21:47:12 UTC, Sasha wrote:
 But one thing that called my attention is that for what I see 
 C++ doesn't has this feature, and proposes were rejected 
 because the problems that would be created with this feature.

 Sasha.
Which pretty much doesn't exist in the existing languages that At most you just add a note in release notes about the functions being renamed. I could see it an issue in dynamic languages like Python, because such a change could pass silently and then crash your program in runtime. But in D it just wouldn't compile, so it's an easy fix.
Feb 12
prev sibling parent Jonathan Marler <johnnymarler gmail.com> writes:
On Wednesday, 12 February 2020 at 21:47:12 UTC, Sasha wrote:
 On Wednesday, 12 February 2020 at 21:11:12 UTC, Jonathan Marler 
 wrote:
 You could use variables to make it look nicer at the 
 call-side, but the downside is there's no guarantee that those 
 variable names have any relation to the names of the 
 parameters. For example, this would still compile:

 makeWindow(x, width, y, height);

 This problem can't happen with named arguments.  Named 
 arguments also saves you if the function arguments change 
 names/meaning, i.e.

 ORIGINAL: void makeWindow(int x, int y, int width, int height)
 MODIFIED: void makeWindow(int left, int top, int right, int 
 bottom);

 The version that doesn't use named arguments will still 
 compile and run:

 makeWindow(x, y, width, height);

 But named arguments would catch the problem at compile-time:

 makeWindow(x: 67, y: 98, width: 100, height: 100); // error no 
 argument named 'x', 'y', 'width', 'height'
OK, now let's see a problem with named arguments, imagine this: makeWindow(x, y, width, height); You can call this function like: makeWindow(x: 67, y: 98, width: 100, height: 100); // Name Arguments makeWindow(67, 98, 100, 100); // Constants makeWindow(x, y, width, height); // Variables So far so good, but later someone decides to rename some parameters to: makeWindow(posx, posy, width, height); // Note: x => posx and y => posy makeWindow(x: 67, y: 98, width: 100, height: 100); // Ops not working anymore! makeWindow(67, 98, 100, 100); // Constants still works makeWindow(x, y, width, height); // Variables Still works What I mean is that we need to balance this better, you showed a defect without Named Arguments and I'm showing a problem with. But one thing that called my attention is that for what I see C++ doesn't has this feature, and proposes were rejected because the problems that would be created with this feature. Sasha.
My point was the the error is caught at compile-time rather than runtime, which I think is a pro in the named arguments column. That being said, the issue you brought up with named arguments is a valid issue and would be my biggest argument against them. They dramatically increase the surface area of the API which will lead to more breakage between libraries. For this reason and the fact that I think named arguments are only useful in a minority of cases (maybe 25%?) I think it would be better to make named arguments "opt-in" so that each library can choose when to make their parameter names apart of their API.
Feb 12
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/11/2020 11:42 PM, aliak wrote:
 Or taking about 1 to 5 minutes depending on how easy documentation is to find, 
 and how bored you are to figure out what this is doing:
As an aside, this is why I encourage URLs to be put right in the source code with links to relevant information like bugzilla issues, spec pages, API documentation, etc.
Feb 12
prev sibling next sibling parent reply Jon Degenhardt <jond noreply.com> writes:
On Friday, 7 February 2020 at 03:33:26 UTC, Jonathan M Davis 
wrote:
 Well, I'll say again that I don't like the idea of having named 
 arguments in the language, because it makes the parameter names 
 part of the API, resulting in yet more bikeshedding and yet 
 another thing that can't be changed without breaking existing 
 code. Once in a while, named arguments may be useful, but for 
 the most part, they're useful because a function has way too 
 many parameters, in which case, the function should have been 
 designed differently.
I am in definitely in favor of named arguments in the language. Overall I think the benefits of this specific DIP proposal outweigh the negatives identified. That said, having parameter names automatically become part of a function's API is a meaningful downside. (Specifically, that a parameter name cannot be changed without risk of breaking existing callers.) The reasons are likely self-evident, but to spell out my thoughts: * Additional design time when initially creating functions (good names are hard). * More time required from code reviewers (both open-source and corporate). * Barrier to incrementally improving a function (and documentation) over-time by improving the quality of the parameter names. The above are more reflective of waterfall than an agile approach, a disadvantage in situations where a more iterative development style is preferable. Another part of the equation is simply that when I'm developing a function, I usually have a pretty good idea whether named arguments are going to be a material benefit. In those cases I'm willing to spend time on the quality of the names. I do think the benefits of the DIP outweigh this concern. However, if there is a reasonable way to allow the developer of a function to control whether the function can invoked via named arguments that would be an enhancement worth considering. This control need not be at the level of each individual parameter. It could be at the function level. --Jon
Feb 08
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 9 February 2020 at 00:56:15 UTC, Jon Degenhardt wrote:
 (Specifically, that a parameter name cannot be changed without 
 risk of breaking existing callers.)
Does it change your view at all that parameter names are *already public* per both spec and reality and have been for a long, long time? (my web.d framework used their availability as early as 2012ish) https://dlang.org/spec/expression.html#IsExpression "the parameter sequence of a function, delegate, or function pointer. This includes the parameter types, names, and default values." And, of course, documentation though that isn't strictly part of the compiler breakage.
Feb 08
parent reply Jon Degenhardt <jond noreply.com> writes:
On Sunday, 9 February 2020 at 01:07:03 UTC, Adam D. Ruppe wrote:
 On Sunday, 9 February 2020 at 00:56:15 UTC, Jon Degenhardt 
 wrote:
 (Specifically, that a parameter name cannot be changed without 
 risk of breaking existing callers.)
Does it change your view at all that parameter names are *already public* per both spec and reality and have been for a long, long time? (my web.d framework used their availability as early as 2012ish) https://dlang.org/spec/expression.html#IsExpression "the parameter sequence of a function, delegate, or function pointer. This includes the parameter types, names, and default values." And, of course, documentation though that isn't strictly part of the compiler breakage.
Probably not, but let me give some thoughts and ask a clarifying question. Main thing - As a pragmatic matter, I'd expect it to be much more likely that named argument invocation would be a source of breakage than usage arising from introspection. Related - There is significant difference between parameter names being public and having the names be sources of backward compatibility in function calls. Now my question - I know function parameters names can be retrieved by type introspection. What I don't know is the ways those names can be used such that programs can break if a parameter names change. Can you give some examples?
Feb 08
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 9 February 2020 at 01:47:35 UTC, Jon Degenhardt wrote:
 Now my question - I know function parameters names can be 
 retrieved by type introspection. What I don't know is the ways 
 those names can be used such that programs can break if a 
 parameter names change. Can you give some examples?
We can do named parameters in a library already, something like: void func(int param) { } int item; callNamed!(func, param => item)(); // possible today. It pulls param name of func and from the given lambda to match up the item. If func's param name were to change, that callNamed would fail, just like with this dip. Of course since the syntax is weird and you need to import a lib... I never use this thing and I doubt anyone else does either. (I can't even find my implementation right now, though I know I have it somewhere). I do use it extensively for runtime things though like generating command line parsers and web apis which can break, but that's expected on that interface anyway so of course I design for it. But my policy on breakage though is I avoid it... unless I specifically mention in the documentation that you can't rely on it. Then if you do, that's your problem. So if I didn't want to do reliable names, I'd just do /// $(WARNING the parameter names are NOT stable and may change without notice. ) and then there we go, disclaimer of liability :)
Feb 08
parent reply Jon Degenhardt <jond noreply.com> writes:
On Sunday, 9 February 2020 at 02:03:42 UTC, Adam D. Ruppe wrote:
 On Sunday, 9 February 2020 at 01:47:35 UTC, Jon Degenhardt 
 wrote:
 Now my question - I know function parameters names can be 
 retrieved by type introspection. What I don't know is the ways 
 those names can be used such that programs can break if a 
 parameter names change. Can you give some examples?
We can do named parameters in a library already, something like: void func(int param) { } int item; callNamed!(func, param => item)(); // possible today. It pulls param name of func and from the given lambda to match up the item. If func's param name were to change, that callNamed would fail, just like with this dip.
That's a useful example, thanks! It doesn't change my overall opinion though. I like the DIP, even this downside. However, it would be an improvement if there was a way for the developer of a function to disable named parameter invocation. Or perhaps a way to discourage it, for example, a compile-time warning about no-backward compatibility for parameter names.
Feb 08
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 9 February 2020 at 02:15:36 UTC, Jon Degenhardt wrote:
 Or perhaps a way to discourage it, for example, a compile-time 
 warning about no-backward compatibility for parameter names.
I would kinda love user-defined warnings. pragma(msg) comes close sometimes but there is no way to conditionally trigger it. (You can sort of conditionally disable via `version()` though.) Of course, you could just name your parameters `_randomNameYouReallyDontWantToUse_like_seriously_dont_rely_on_this_name_lol` :P A reasonable thing for the compiler to do btw would be to call out when function names change. Suppose you have: foo(bar: 1, baz: 4) and later you change the signature to foo(int bar, int coolness) the compiler could reasonably issue an error: error: foo has no parameter named `baz`. Did you mean `coolness`? based on process of elimination to suggest the names not yet specified to ease transition.
Feb 08
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09.02.20 03:31, Adam D. Ruppe wrote:
 On Sunday, 9 February 2020 at 02:15:36 UTC, Jon Degenhardt wrote:
 Or perhaps a way to discourage it, for example, a compile-time warning 
 about no-backward compatibility for parameter names.
I would kinda love user-defined warnings. pragma(msg) comes close sometimes but there is no way to conditionally trigger it. (You can sort of conditionally disable via `version()` though.) Of course, you could just name your parameters `_randomNameYouReallyDontWantToUse_like_seriously_dont_rely_on_this_name_lol` :P
int justDoThis(int,int){ return _param_0+_param_1; }
Feb 11
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/8/2020 6:31 PM, Adam D. Ruppe wrote:
 I would kinda love user-defined warnings. pragma(msg) comes close sometimes
but 
 there is no way to conditionally trigger it.
static if (condition) pragma(msg, "Look, Ma!"); Or static assert().
 A reasonable thing for the compiler to do btw would be to call out when
function 
 names change. Suppose you have:
 
 foo(bar: 1, baz: 4)
 
 and later you change the signature to
 
 foo(int bar, int coolness)
 
 the compiler could reasonably issue an error:
 
 error: foo has no parameter named `baz`. Did you mean `coolness`?
 
 based on process of elimination to suggest the names not yet specified to ease 
 transition.
Note that the compiler already uses a spell checker to look for close symbol matches.
Feb 12
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 13 February 2020 at 01:37:58 UTC, Walter Bright 
wrote:
     static if (condition) pragma(msg, "Look, Ma!");
In this context, the condition there would be someone using the parameter names. That's impossible to find in static if.
 Note that the compiler already uses a spell checker to look for 
 close symbol matches.
A spell checker wouldn't necessarily catch a name change like this since the distance between old and new name may be significant. (e.g. ms to milliseconds has an edit distance of ... what, 11?) The current spell checker doesn't do it: int milliseconds() { return 0; } void main() { int a = ms(); } // wer.d(4): Error: undefined identifier ms // note no suggestion given But since the number of parameters is so limited, process of elimination means even with a very large edit distance, it is still probable that you meant one of the few missing parameters. Like dmd will right now suggest: wer.d(4): Error: function wer.milliseconds(int ms) is not callable using argument types () So a natural extension of this could be given named argument `milliseconds` does not match any parameter And just those two messages next to each other, spell check or no, would probably clue the user in. I doubt this will even need additional code, but nevertheless, given the importance of good error messages to user productivity, I think all DIPs ought to have a section on diagnostics and any implementation should ensure it is addressed one way or another.
Feb 12
parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/12/2020 6:00 PM, Adam D. Ruppe wrote:
 And just those two messages next to each other, spell check or no, would 
 probably clue the user in. I doubt this will even need additional code, but 
 nevertheless, given the importance of good error messages to user
productivity, 
 I think all DIPs ought to have a section on diagnostics and any implementation 
 should ensure it is addressed one way or another.
It's a good idea, but I've found it to be pragmatic to not worry much about error message quality during the initial implementation, just focus on getting the semantics right. (Doing great error messages often is a significant increase in complexity.) Having some experience with the kinds of mistakes people tend to make (and it isn't random) helps a lot to guide error message development. Hence is it something for the future, and is premature to add in the DIP for the feature. Doing it later also would not require a DIP. Good error messages are always a work in progress.
Feb 13
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/8/20 8:47 PM, Jon Degenhardt wrote:
 On Sunday, 9 February 2020 at 01:07:03 UTC, Adam D. Ruppe wrote:
 On Sunday, 9 February 2020 at 00:56:15 UTC, Jon Degenhardt wrote:
 (Specifically, that a parameter name cannot be changed without risk 
 of breaking existing callers.)
Does it change your view at all that parameter names are *already public* per both spec and reality and have been for a long, long time? (my web.d framework used their availability as early as 2012ish) https://dlang.org/spec/expression.html#IsExpression "the parameter sequence of a function, delegate, or function pointer. This includes the parameter types, names, and default values." And, of course, documentation though that isn't strictly part of the compiler breakage.
Probably not, but let me give some thoughts and ask a clarifying question. Main thing - As a pragmatic matter, I'd expect it to be much more likely that named argument invocation would be a source of breakage than usage arising from introspection. Related - There is significant difference between parameter names being public and having the names be sources of backward compatibility in function calls.
If you name your parameters something unintuitive, like "a". Likely nobody is going to use them via named parameters. For example, if you have; Date makeDate(int year, int month, int day) What would be the reason to change these? Likely you already picked those names. But if you named them: Date makeDate(int a, int b, int c) Now, changing it to the more appropriate names as above would be technically a "breaking change". But who cares? Nobody is writing makeDate(b: 1, c: 2, a: 3), and if they are, they deserve broken code IMO. I don't think there's going to be a lot of problems here. Take a look at the history of phobos and see if you can find places where someone changed an appropriate parameter name to another appropriate name. Chances are it's close to never. And even if it was changed, is the change something that would have to be made? Was the original parameter name so bad that it needed changing in light of the code breakage that would now take place? The one annoying downside is that there is no possibly way to deprecate this. You can't have: deprecated("use better names please") Date makeDate(int a, int b, int c) Date makeDate(int year, int month, int day) This is one huge departure from current mechanisms. -Steve
Feb 08
parent reply Jon Degenhardt <jond noreply.com> writes:
On Sunday, 9 February 2020 at 02:40:30 UTC, Steven Schveighoffer 
wrote:
 On 2/8/20 8:47 PM, Jon Degenhardt wrote:
 On Sunday, 9 February 2020 at 01:07:03 UTC, Adam D. Ruppe 
 wrote:
 On Sunday, 9 February 2020 at 00:56:15 UTC, Jon Degenhardt 
 wrote:
 (Specifically, that a parameter name cannot be changed 
 without risk of breaking existing callers.)
[...snip...] If you name your parameters something unintuitive, like "a". Likely nobody is going to use them via named parameters. For example, if you have; Date makeDate(int year, int month, int day) What would be the reason to change these? Likely you already picked those names. But if you named them: Date makeDate(int a, int b, int c)
Well, I personally wouldn't recommend this as a general remedy. Parameter names help to document the implementation. In many environments it's important that developers other than the original author be able to read, debug, enhance, or take over code. Having good parameter and variable names is helpful from this perspective. Naming conventions are a common element of coding standards for this reason. In general, what I typically try to do (and recommend) is taking a good shot at creating meaningful names, but not spend excessive amounts of time on it. And, depending the situation, look at improving the names over time (and other elements of the code as well).
 I don't think there's going to be a lot of problems here. Take 
 a look at the history of phobos and see if you can find places 
 where someone changed an appropriate parameter name to another 
 appropriate name. Chances are it's close to never.
For Phobos this would be my expectation as well. I'm admittedly thinking of project environments with meaningful size teams more than the standard library of a major programming language. Environments where there is a fair bit of code in earlier stages of development and subject to more evolution.
Feb 08
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/8/20 11:10 PM, Jon Degenhardt wrote:
 For Phobos this would be my expectation as well. I'm admittedly thinking 
 of project environments with meaningful size teams more than the 
 standard library of a major programming language. Environments where 
 there is a fair bit of code in earlier stages of development and subject 
 to more evolution.
I think the evolution goes like this: void foo(int tmpName); ... // all callers: foo(5); // didn't use named parameters because I have no idea what "tmpName" means now, we evolve foo: void foo(int milliseconds); Now, all calls still work because nobody used the bad name as "documentation". New calls now use the name sometimes because it's helpful. My point is simply that the name itself is going to not require, but probably result in, people using or not using the name. Bad names naturally aren't going to get name usage, because they suck and aren't helpful. Good names are. I understand though, there are possible bikeshed problems here. For example, someone who implements foo might be tired of typing out "milliseconds" and change the parameter name to "ms". Now that person has to worry about what happens for callers. So instead he has to leave milliseconds in the name, and create a temporary ms in his function. At that point, you have to weigh how important it is to change that parameter name against the breakage that might occur. How much does it cost to repaint the shed? Might not be worth it. Note that Swift (which has parameter names as part of the function name) has a mechanism to deal with this. A function in swift looks like: func foo(a : int) -> Void You MUST call the function with foo(a: 5). foo(5) doesn't work. But you can name the parameter to the outside and name the parameter differently on the inside: func foo(milliseconds a: int) -> Void Now, you call the function with foo(milliseconds: 5), and inside the function, the parameter is named 'a'. Not sure this could be doable in D. But for a main language that started out with significant naming of parameters (inheriting this from objective-C), it's a good place to look for inspiration here. -Steve
Feb 09
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 9 February 2020 at 18:32:45 UTC, Steven Schveighoffer 
wrote:
 Now, you call the function with foo(milliseconds: 5), and 
 inside the function, the parameter is named 'a'.
We can always just `alias a = milliseconds;` inside the function. Changing inside alone is easy, though changing the outside one is a bit trickier. We can't overload on name alone so no way to use function-level `deprecated` messages. But maybe a pragma or deprecated alias syntax on names could be enough. Users changing is easy too, just the lib implementer wanting to provide some range of compatibility would probably want the deprecated alias to keep working for a while. So we might consider adding such a thing. void foo(int milliseconds deprecated alias ms) {} wow ugly syntax lol but i think the grammar would allow that and now the param has two names for inside and outside and gives a place for us to put a message. but i kinda suggest just not worrying about it until experience proves this is a real problem that needs to be solved.
Feb 09
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/9/20 1:45 PM, Adam D. Ruppe wrote:
 On Sunday, 9 February 2020 at 18:32:45 UTC, Steven Schveighoffer wrote:
 Now, you call the function with foo(milliseconds: 5), and inside the 
 function, the parameter is named 'a'.
We can always just `alias a = milliseconds;` inside the function. Changing inside alone is easy, though changing the outside one is a bit trickier. We can't overload on name alone so no way to use function-level `deprecated` messages. But maybe a pragma or deprecated alias syntax on names could be enough. Users changing is easy too, just the lib implementer wanting to provide some range of compatibility would probably want the deprecated alias to keep working for a while. So we might consider adding such a thing. void foo(int milliseconds deprecated alias ms) {} wow ugly syntax lol but i think the grammar would allow that and now the param has two names for inside and outside and gives a place for us to put a message. but i kinda suggest just not worrying about it until experience proves this is a real problem that needs to be solved.
Agree with all of this. -Steve
Feb 09
prev sibling next sibling parent Paul Backus <snarwin gmail.com> writes:
On Sunday, 9 February 2020 at 18:32:45 UTC, Steven Schveighoffer 
wrote:
 But you can name the parameter to the outside and name the 
 parameter differently on the inside:

 func foo(milliseconds a: int) -> Void

 Now, you call the function with foo(milliseconds: 5), and 
 inside the function, the parameter is named 'a'.

 Not sure this could be doable in D. But for a main language 
 that started out with significant naming of parameters 
 (inheriting this from objective-C), it's a good place to look 
 for inspiration here.

 -Steve
You can alias the parameter inside the function: void foo(int milliseconds) { alias ms = milliseconds; // Use 'ms' from here on // ... }
Feb 09
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/9/2020 10:32 AM, Steven Schveighoffer wrote:
 Not sure this could be doable in D. But for a main language that started out 
 with significant naming of parameters (inheriting this from objective-C), it's
a 
 good place to look for inspiration here.
Since parameter names are not part of the name mangling, you can do things like: ---- A.di void foo(int x); ---- A.d void foo(int y) { ... } And, of course, you can also do: ---- A.di void foo(int); ---- A.d void foo(int y) { ... }
Feb 09
prev sibling next sibling parent reply Jon Degenhardt <jond noreply.com> writes:
On Sunday, 9 February 2020 at 18:32:45 UTC, Steven Schveighoffer 
wrote:
 On 2/8/20 11:10 PM, Jon Degenhardt wrote:
 For Phobos this would be my expectation as well. I'm 
 admittedly thinking of project environments with meaningful 
 size teams more than the standard library of a major 
 programming language. Environments where there is a fair bit 
 of code in earlier stages of development and subject to more 
 evolution.
I think the evolution goes like this: void foo(int tmpName); ... // all callers: foo(5); // didn't use named parameters because I have no idea what "tmpName" means now, we evolve foo: void foo(int milliseconds); Now, all calls still work because nobody used the bad name as "documentation". New calls now use the name sometimes because it's helpful. My point is simply that the name itself is going to not require, but probably result in, people using or not using the name. Bad names naturally aren't going to get name usage, because they suck and aren't helpful. Good names are. I understand though, there are possible bikeshed problems here. For example, someone who implements foo might be tired of typing out "milliseconds" and change the parameter name to "ms". Now that person has to worry about what happens for callers. So instead he has to leave milliseconds in the name, and create a temporary ms in his function. At that point, you have to weigh how important it is to change that parameter name against the breakage that might occur. How much does it cost to repaint the shed? Might not be worth it.
Yes, this is representative of what I had in mind. Another is changes in the ambiguity of a name. As an example, assume 'height' is an important element of a number of calculations in a system. Early on there is no ambiguity about what 'height' means. The word 'height' gets used in the names of functions, parameters, variables, etc. Then use cases arise where it is important to distinguish interior and exterior heights, so names like 'interiorHeight' and 'exteriorHeight' are preferable. Over time the name 'height' by itself becomes more and more ambiguous. Any place the name 'height' is exposed in a manner that other code becomes dependent on the name is a source of technical debt. Often this form of technical debt just happens. It's hard to predict these changes. But developers often do spend time thinking about forward compatibility of names that are part of a public API contract. This DIP will increase this surface area. As I said, I don't think this is a deal breaker for the DIP. I think it is a positive change even with this downside. My only recommendation is to consider whether there are mechanisms that can help reduce this form technical debt, without requiring material additional developer time when initially writing code. My thought was to allow explicit expression by the developer of whether a function was intended for named argument invocation (several possibilities). But there may be other approaches to achieving the same goal. For example, considering what Swift does:
 Note that Swift (which has parameter names as part of the 
 function name) has a mechanism to deal with this.

 [... details excluded... ]

 Not sure this could be doable in D. But for a main language 
 that started out with significant naming of parameters 
 (inheriting this from objective-C), it's a good place to look 
 for inspiration here.
This is very nice callout. Even if it cannot be done in D just putting it consideration set is worthwhile. Also, several people have pointed out that aliasing parameter names within functions can help with these cases. I agree. It doesn't completely address the issue, but it is helpful, and a tool I hadn't thought of. --Jon
Feb 09
parent FeepingCreature <feepingcreature gmail.com> writes:
On Sunday, 9 February 2020 at 21:05:43 UTC, Jon Degenhardt wrote:
 As an example, assume 'height' is an important element of a 
 number of calculations in a system. Early on there is no 
 ambiguity about what 'height' means. The word 'height' gets 
 used in the names of functions, parameters, variables, etc. 
 Then use cases arise where it is important to distinguish 
 interior and exterior heights, so names like 'interiorHeight' 
 and 'exteriorHeight' are preferable.

 Over time the name 'height' by itself becomes more and more 
 ambiguous. Any place the name 'height' is exposed in a manner 
 that other code becomes dependent on the name is a source of 
 technical debt.

 Often this form of technical debt just happens. It's hard to 
 predict these changes. But developers often do spend time 
 thinking about forward compatibility of names that are part of 
 a public API contract. This DIP will increase this surface area.

 As I said, I don't think this is a deal breaker for the DIP. I 
 think it is a positive change even with this downside. My only 
 recommendation is to consider whether there are mechanisms that 
 can help reduce this form technical debt, without requiring 
 material additional developer time when initially writing code.
I feel like this increase in surface area is actually straightforwardly a good thing. Even if the parameter is not used as a named parameter, we are seeing a shift in the meaning of the parameter as understood by the caller. With the DIP, this change in meaning will necessarily lead to a reevaluation of the callsite and clarification of whether you meant interiorHeight or exteriorHeight. With the current state of affairs, absent a change in type, there is absolutely no indication to the caller that their call has become ambiguous. Again, the thing that is happening here is a drift in meaning, which is *already* a breaking change of the API. The language has simply previously allowed developers to obfuscate and ignore this fact. Inasmuch as this DIP makes this more difficult, it's a benefit, not a drawback.
Feb 09
prev sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 10/02/2020 7:32 AM, Steven Schveighoffer wrote:
 
 Not sure this could be doable in D. But for a main language that started 
 out with significant naming of parameters (inheriting this from 
 objective-C), it's a good place to look for inspiration here.
Alternatively support implicit construction of structs as parameters i.e. void foo(Nullable!int ms); foo(ms: 3); You have to do some mapping internally but it means even if you deprecate a name, you can still keep the old ones.
Feb 09
parent reply rb3 <ryanblonna3 gmail.com> writes:
On Monday, 10 February 2020 at 02:25:07 UTC, rikki cattermole 
wrote:
 On 10/02/2020 7:32 AM, Steven Schveighoffer wrote:
 
 Not sure this could be doable in D. But for a main language 
 that started out with significant naming of parameters 
 (inheriting this from objective-C), it's a good place to look 
 for inspiration here.
Alternatively support implicit construction of structs as parameters i.e. void foo(Nullable!int ms); foo(ms: 3); You have to do some mapping internally but it means even if you deprecate a name, you can still keep the old ones.
This sounds like a good unification between struct initialization and named arguments. So to "enable" named arguments, one would simply declare a struct like this: struct BufferCreateInfo { const(char)* type; size_t size; } and then use the struct type in a function argument list: Buffer createBuffer(BufferCreateInfo info); and call it like this: auto buffer = createBuffer({ type: "BufferType", size: 16 }); // or createBuffer(type: "BufferType", size: 16) for syntax sugar or if you want mixed named and non-named arguments: Buffer createBuffer(BufferCreateInfo info, size_t howMany); // createBuffer(type: "BufferType", size: 16, 10); The only change is allowing struct construction on a function parameter, then maybe take it a step further by eliminating the curly braces in function calls. But I don't know anything about compilers...
Feb 09
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 10/02/2020 5:31 PM, rb3 wrote:
 On Monday, 10 February 2020 at 02:25:07 UTC, rikki cattermole wrote:
 On 10/02/2020 7:32 AM, Steven Schveighoffer wrote:
 Not sure this could be doable in D. But for a main language that 
 started out with significant naming of parameters (inheriting this 
 from objective-C), it's a good place to look for inspiration here.
Alternatively support implicit construction of structs as parameters i.e. void foo(Nullable!int ms); foo(ms: 3); You have to do some mapping internally but it means even if you deprecate a name, you can still keep the old ones.
This sounds like a good unification between struct initialization and named arguments. So to "enable" named arguments, one would simply declare a struct like this: struct BufferCreateInfo {     const(char)* type;     size_t size; } and then use the struct type in a function argument list: Buffer createBuffer(BufferCreateInfo info); and call it like this: auto buffer = createBuffer({ type: "BufferType", size: 16 }); // or createBuffer(type: "BufferType", size: 16) for syntax sugar or if you want mixed named and non-named arguments: Buffer createBuffer(BufferCreateInfo info, size_t howMany); // createBuffer(type: "BufferType", size: 16, 10); The only change is allowing struct construction on a function parameter, then maybe take it a step further by eliminating the curly braces in function calls. But I don't know anything about compilers...
That is not what I suggested. What I suggested was given a single argument, automatically construct+call the constructor on a struct as defined in a parameter. It is a 1 to 1 rewrite and would be very simple to do.
Feb 09
parent reply rb3 <ryanblonna3 gmail.com> writes:
On Monday, 10 February 2020 at 04:36:17 UTC, rikki cattermole 
wrote:
 That is not what I suggested.

 What I suggested was given a single argument, automatically 
 construct+call the constructor on a struct as defined in a 
 parameter.

 It is a 1 to 1 rewrite and would be very simple to do.
That sounds like what I just described. Not sure what the difference is. Anyway, there's already a PR for what I described written by Wilzbach, it was opened in 2017: https://github.com/dlang/DIPs/pull/71. Is this not the same as what you suggested?
Feb 09
parent rikki cattermole <rikki cattermole.co.nz> writes:
On 10/02/2020 5:47 PM, rb3 wrote:
 On Monday, 10 February 2020 at 04:36:17 UTC, rikki cattermole wrote:
 That is not what I suggested.

 What I suggested was given a single argument, automatically 
 construct+call the constructor on a struct as defined in a parameter.

 It is a 1 to 1 rewrite and would be very simple to do.
That sounds like what I just described. Not sure what the difference is. Anyway, there's already a PR for what I described written by Wilzbach, it was opened in 2017: https://github.com/dlang/DIPs/pull/71. Is this not the same as what you suggested?
I have commented on that PR. The difference is: 1. in place struct initialization supports multiple arguments 2. and it requires extra syntax during construction 3. and finally is fully replaced by this DIP
Feb 09
prev sibling parent Zoadian <no no.no> writes:
On Sunday, 9 February 2020 at 01:47:35 UTC, Jon Degenhardt wrote:
 On Sunday, 9 February 2020 at 01:07:03 UTC, Adam D. Ruppe wrote:
 [...]
Probably not, but let me give some thoughts and ask a clarifying question. Main thing - As a pragmatic matter, I'd expect it to be much more likely that named argument invocation would be a source of breakage than usage arising from introspection. Related - There is significant difference between parameter names being public and having the names be sources of backward compatibility in function calls. Now my question - I know function parameters names can be retrieved by type introspection. What I don't know is the ways those names can be used such that programs can break if a parameter names change. Can you give some examples?
vibe.d uses parameter names to generate REST api bindings see: https://vibed.org/docs#rest-interface-generator
Feb 09
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/8/2020 4:56 PM, Jon Degenhardt wrote:
 That said, having parameter names automatically become part of a function's
API 
 is a meaningful downside. (Specifically, that a parameter name cannot be
changed 
 without risk of breaking existing callers.)
Note that D already has "named parameters" for struct initializers. That means, for example, that the names of the struct field cannot be changed without breaking any initializer relying on it. I've never heard a single comment about this, let alone any complaint, nor any indication that anyone's code broke.
Feb 09
parent reply Arine <arine123445128843 gmail.com> writes:
On Sunday, 9 February 2020 at 19:45:20 UTC, Walter Bright wrote:
 On 2/8/2020 4:56 PM, Jon Degenhardt wrote:
 That said, having parameter names automatically become part of 
 a function's API is a meaningful downside. (Specifically, that 
 a parameter name cannot be changed without risk of breaking 
 existing callers.)
Note that D already has "named parameters" for struct initializers. That means, for example, that the names of the struct field cannot be changed without breaking any initializer relying on it. I've never heard a single comment about this, let alone any complaint, nor any indication that anyone's code broke.
struct A { int foo; } struct A { int bar; // renamed from foo deprecated alias foo = bar; }; False equivalency, you have many tools at your disposal to deal with this for structs. Also found a bug. A a = { foo: 10 }; // no deprecation warning, when foo is the deprecated alias
Feb 09
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/9/2020 11:51 AM, Arine wrote:
 Also found a bug.
Please report all bugs to bugzilla.
Feb 09
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/9/2020 11:51 AM, Arine wrote:
 struct A {
     int foo;
 }
 
 struct A {
      int bar; // renamed from foo
      deprecated alias foo = bar;
 };
 
 
 False equivalency, you have many tools at your disposal to deal with this for 
 structs.
C has it, too. Never heard a single complaint about it, either. https://en.cppreference.com/w/c/language/struct_initialization
Feb 09
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09.02.20 21:59, Walter Bright wrote:
 On 2/9/2020 11:51 AM, Arine wrote:
 struct A {
     int foo;
 }

 struct A {
      int bar; // renamed from foo
      deprecated alias foo = bar;
 };


 False equivalency, you have many tools at your disposal to deal with 
 this for structs.
C has it, too. Never heard a single complaint about it, either. https://en.cppreference.com/w/c/language/struct_initialization
If you change the name of a field, code that accesses the field in the standard way also breaks. It would be rather weird if people complained specifically about broken initializers.
Feb 11
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/11/2020 12:49 AM, Timon Gehr wrote:
 If you change the name of a field, code that accesses the field in the
standard 
 way also breaks. It would be rather weird if people complained specifically 
 about broken initializers.
If the code followed good encapsulation techniques, it wouldn't any more than changing the name of a parameter would necessitate changing the body of the function.
Feb 12
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 13.02.20 02:40, Walter Bright wrote:
 On 2/11/2020 12:49 AM, Timon Gehr wrote:
 If you change the name of a field, code that accesses the field in the 
 standard way also breaks. It would be rather weird if people 
 complained specifically about broken initializers.
If the code followed good encapsulation techniques, it wouldn't any more than changing the name of a parameter would necessitate changing the body of the function.
Which is exactly what defeats the argument that spawned this sub-thread.
Feb 19
prev sibling parent reply Arine <arine123445128843 gmail.com> writes:
On Sunday, 9 February 2020 at 20:59:52 UTC, Walter Bright wrote:
 On 2/9/2020 11:51 AM, Arine wrote:
 struct A {
     int foo;
 }
 
 struct A {
      int bar; // renamed from foo
      deprecated alias foo = bar;
 };
 
 
 False equivalency, you have many tools at your disposal to 
 deal with this for structs.
C has it, too. Never heard a single complaint about it, either. https://en.cppreference.com/w/c/language/struct_initialization
struct A { int foo; }; struct A { union { int foo; int bar; // renamed to bar }; }; struct A a = { .foo = 10 }; False equivalency, you have some tools at your disposal to deal with this for structs in C.
Feb 11
parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Tuesday, 11 February 2020 at 15:11:18 UTC, Arine wrote:
 On Sunday, 9 February 2020 at 20:59:52 UTC, Walter Bright wrote:
 On 2/9/2020 11:51 AM, Arine wrote:
 struct A {
     int foo;
 }
 
 struct A {
      int bar; // renamed from foo
      deprecated alias foo = bar;
 };
 
 
 False equivalency, you have many tools at your disposal to 
 deal with this for structs.
C has it, too. Never heard a single complaint about it, either. https://en.cppreference.com/w/c/language/struct_initialization
struct A { int foo; }; struct A { union { int foo; int bar; // renamed to bar }; };
only since C11. anonymous unions and structs are gcc extension (or C++).
 struct A a = { .foo = 10 };

 False equivalency, you have some tools at your disposal to deal 
 with this for structs in C.
Feb 11
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/6/20 10:33 PM, Jonathan M Davis wrote:
 Once in a while, named arguments may
 be useful, but for the most part, they're useful because a function has way
 too many parameters, in which case, the function should have been designed
 differently.
I find this assertion lacking evidence. How does one design a constructor that initializes all the fields of a type without including all the parameters to initialize that type? If you reduce the number of parameters, what do you do with the data not specified? I suppose you can just have a minimal constructor and then just expect the user to set all the pieces up, but what if you need to use it in an expression? How do you decide which pieces are "important" enough to initialize first, and which ones get initialized later? What if the parameters are initializing things that can only be initialized in the constructor (e.g. immutable data). I focus on constructors because structs ALREADY support named parameters in this instance (when there is a lack of constructor), and we haven't seen the problems you are asserting. I can imagine with this DIP instead of 15 different constructors for all the different ways you want to construct said type (yes, I've seen this kind of stuff), you have one that has default arguments for all of the optional pieces (or maybe you split them up with ones that can be safe/pure and ones that can't, etc). And then the call interface is much better looking and self-explanatory. And I like that you can pick which way you want to call it, even for individual parameters. -Steve
Feb 10
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Feb 10, 2020 at 01:27:49PM -0500, Steven Schveighoffer via
Digitalmars-d wrote:
 On 2/6/20 10:33 PM, Jonathan M Davis wrote:
 Once in a while, named arguments may be useful, but for the most
 part, they're useful because a function has way too many parameters,
 in which case, the function should have been designed differently.
I find this assertion lacking evidence. How does one design a constructor that initializes all the fields of a type without including all the parameters to initialize that type?
[...] Ostensibly, by encapsulating the parameters into a struct and passing said struct up the ctor chain. ;-) T -- English has the lovely word "defenestrate", meaning "to execute by throwing someone out a window", or more recently "to remove Windows from a computer and replace it with something useful". :-) -- John Cowan
Feb 10
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/10/20 1:36 PM, H. S. Teoh wrote:
 On Mon, Feb 10, 2020 at 01:27:49PM -0500, Steven Schveighoffer via
Digitalmars-d wrote:
 On 2/6/20 10:33 PM, Jonathan M Davis wrote:
 Once in a while, named arguments may be useful, but for the most
 part, they're useful because a function has way too many parameters,
 in which case, the function should have been designed differently.
I find this assertion lacking evidence. How does one design a constructor that initializes all the fields of a type without including all the parameters to initialize that type?
[...] Ostensibly, by encapsulating the parameters into a struct and passing said struct up the ctor chain. ;-)
So basically, for each type you need to define another type to pass parameters? Sounds... excessive ;) And the benefit of having a POD struct to pass as a parameter to cut down on constructor parameters is... you get named parameters! -Steve
Feb 10
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Feb 10, 2020 at 01:39:12PM -0500, Steven Schveighoffer via
Digitalmars-d wrote:
 On 2/10/20 1:36 PM, H. S. Teoh wrote:
 On Mon, Feb 10, 2020 at 01:27:49PM -0500, Steven Schveighoffer via
Digitalmars-d wrote:
 On 2/6/20 10:33 PM, Jonathan M Davis wrote:
 Once in a while, named arguments may be useful, but for the most
 part, they're useful because a function has way too many
 parameters, in which case, the function should have been
 designed differently.
I find this assertion lacking evidence. How does one design a constructor that initializes all the fields of a type without including all the parameters to initialize that type?
[...] Ostensibly, by encapsulating the parameters into a struct and passing said struct up the ctor chain. ;-)
So basically, for each type you need to define another type to pass parameters? Sounds... excessive ;) And the benefit of having a POD struct to pass as a parameter to cut down on constructor parameters is... you get named parameters!
[...] And there you have it, we already have named parameters. :-P Albeit in a verbose, circumlocutious way. :-P T -- English has the lovely word "defenestrate", meaning "to execute by throwing someone out a window", or more recently "to remove Windows from a computer and replace it with something useful". :-) -- John Cowan
Feb 10
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/10/2020 10:39 AM, Steven Schveighoffer wrote:
 [...]
Thanks, you said it better than I!
Feb 10
prev sibling next sibling parent Panke <tobias pankrath.net> writes:
On Monday, 10 February 2020 at 18:27:49 UTC, Steven Schveighoffer 
wrote:
 On 2/6/20 10:33 PM, Jonathan M Davis wrote:
 Once in a while, named arguments may
 be useful, but for the most part, they're useful because a 
 function has way
 too many parameters, in which case, the function should have 
 been designed
 differently.
I find this assertion lacking evidence.
Let me give a data point to the contrary. I am a C++ programmer at work and using CLion as my IDE. Recently CLion got the ability to display parameter names inline at call sides, that is given a function invocation
 foo(bar, baz, baraz)
of a function
 foo(parametertype1 parametername1, parametertype2 
 parametername2, ptype3 pname3)
it will be displayed like this with the parameter names in a slight gray:
 foo(parametername1: bar, parametername2: baz, pname3: baraz).
This already saved hours by preventing bugs and is unanimously considered an improvement by all my colleagues. I am convinced named parameters can improve code quality and even expect that tooling will show up to insert them automatically in existing code, when they get into the language.
Feb 10
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, February 10, 2020 11:27:49 AM MST Steven Schveighoffer via 
Digitalmars-d wrote:
 On 2/6/20 10:33 PM, Jonathan M Davis wrote:
 Once in a while, named arguments may
 be useful, but for the most part, they're useful because a function has
 way too many parameters, in which case, the function should have been
 designed differently.
I find this assertion lacking evidence. How does one design a constructor that initializes all the fields of a type without including all the parameters to initialize that type? If you reduce the number of parameters, what do you do with the data not specified? I suppose you can just have a minimal constructor and then just expect the user to set all the pieces up, but what if you need to use it in an expression? How do you decide which pieces are "important" enough to initialize first, and which ones get initialized later? What if the parameters are initializing things that can only be initialized in the constructor (e.g. immutable data). I focus on constructors because structs ALREADY support named parameters in this instance (when there is a lack of constructor), and we haven't seen the problems you are asserting. I can imagine with this DIP instead of 15 different constructors for all the different ways you want to construct said type (yes, I've seen this kind of stuff), you have one that has default arguments for all of the optional pieces (or maybe you split them up with ones that can be safe/pure and ones that can't, etc). And then the call interface is much better looking and self-explanatory. And I like that you can pick which way you want to call it, even for individual parameters.
The only time that the struct initialization equivalent of named parameters comes into play is when you have a POD type which exposes its member variables. Most structs don't do that, because it's usually bad practice to expose members that way unless they're POD types, and most structs aren't POD types. They usually encpasulate their data and have functions for manipulating it. So, while struct initializers may exist in the language, they're very limited in how they can be used, whereas named arguments could be used pretty much anywhere. I have rarely seen structs where it made sense to have a long list of parameters to their constructors. In almost all cases, when that sort of thing happens, it makes far more sense to group such data into multiple structs so that the data is more organized instead of a huge blob of values all shoved directly into a single object. And in general, if a function parameter list is long, it's usually because the API didn't use structs to group and encapsulate data cleanly. I have rarely seen code where I would have considered it reasonable to have a large list of parameters to a function. As far as I can tell, named parameters are primarily an excuse to be able to have overly long parameter lists instead of properly organizing data, and they encourage what I would consider to be poor programming practices. Regardless, my biggest problem with this DIP (and any DIP with named arguments) is that it adds function parameter names to the API. IMHO, it adds minimal benefit, and in return, it adds yet another set of names which are going to be bikeshedded, and yet another thing that you can't change without risking breaking code. If D were set up so that you normally had function prototypes separate from the functions themselves like you do in C/C++, I would almost certainly stop putting names on _any_ function prototypes if named parameters were added. I don't want to have to worry about breaking someone else's code because of a change to a parameter's name, and IMHO, there are already far too many arguments over the names of functions and types without adding parameter names to the list. - Jonathan M Davis
Feb 11
prev sibling next sibling parent Jesse Phillips <Jesse.K.Phillips+D gmail.com> writes:
On Friday, 7 February 2020 at 03:33:26 UTC, Jonathan M Davis 
wrote:
 Once in a while, named arguments may be useful, but for the 
 most part, they're useful because a function has way too many 
 parameters, in which case, the function should have been 
 designed differently.
I've had the opportunity to design some methods relying on named methods having too many arguments comes from parameters being positional. I find the old advice to package it into a structure as pretending like you're reducing the number of arguments. While a method with many arguments would indicate doing too many things, but I think as you move up in the call stack you have to add to all the different functionality you're trying to abstract away.
Feb 10
prev sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Friday, 7 February 2020 at 03:33:26 UTC, Jonathan M Davis 
wrote:
 but for the most part, they're useful because a function has 
 way too many parameters, in which case, the function should 
 have been designed differently.
Named parameters are not just for when there are too many parameters. Easy example: dup2(a, b); vs dup2(src: a, dst: b);
Feb 19
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, February 19, 2020 8:31:00 AM MST Yuxuan Shui via Digitalmars-d 
wrote:
 On Friday, 7 February 2020 at 03:33:26 UTC, Jonathan M Davis

 wrote:
 but for the most part, they're useful because a function has
 way too many parameters, in which case, the function should
 have been designed differently.
Named parameters are not just for when there are too many parameters. Easy example: dup2(a, b); vs dup2(src: a, dst: b);
Named arguments are completely unnecessary in such a situation. The list of arguments is short enough that it's trivial to know which is which and what they're for. Having the parameter names listed at the call site is just unnecessary cruft, and having named arguments in the language opens up the whole issue of whether the names src and dst were the best names for dup2. Just like there's often too much arguing over what a function should be named, you then have arguing over what the function's parameters should be named and whether they're consistent with other functions, which isn't an issue right now. Right now, if the programmer maintaining dup2 wants to change the parameter names as part of working on the function's implementation, doing so is not a problem, whereas with named arguments, it would break code. Personally, I don't think that named arguments provide much value, and I _really_ don't want parameters to become part of the API. We have enough bikeshedding over names as it is and don't need to introduce yet more ways that changing libraries can break existing code. Unfortunately, given Walter's current position on this, I'm likely going to have to deal with named arguments and the problems that they bring, but I really don't have much good to say about them, and I do not look forward to having to deal with them in the least. - Jonathan M Davis
Feb 19
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 19 February 2020 at 19:13:01 UTC, Jonathan M Davis 
wrote:
      dup2(src: a, dst: b);
Named arguments are completely unnecessary in such a situation. The list of arguments is short enough that it's trivial to know which is which and what they're for.
Eh, the thing with these is it is really easy to do it backwards. I come from intel assembly so I always think it is `mov dst, src`. Unless it is `cp src dst` which is the one exception baked into my brain. So listing it here can legitimately be useful as a reminder when you aren't sure which style this particular function used.
Feb 19
prev sibling next sibling parent reply bachmeier <no spam.net> writes:
On Wednesday, 19 February 2020 at 19:13:01 UTC, Jonathan M Davis 
wrote:
 On Wednesday, February 19, 2020 8:31:00 AM MST Yuxuan Shui via 
 Digitalmars-d wrote:
 On Friday, 7 February 2020 at 03:33:26 UTC, Jonathan M Davis

 wrote:
 but for the most part, they're useful because a function has 
 way too many parameters, in which case, the function should 
 have been designed differently.
Named parameters are not just for when there are too many parameters. Easy example: dup2(a, b); vs dup2(src: a, dst: b);
Named arguments are completely unnecessary in such a situation. The list of arguments is short enough that it's trivial to know which is which and what they're for. Having the parameter names listed at the call site is just unnecessary cruft, and having named arguments in the language opens up the whole issue of whether the names src and dst were the best names for dup2. Just like there's often too much arguing over what a function should be named, you then have arguing over what the function's parameters should be named and whether they're consistent with other functions, which isn't an issue right now. Right now, if the programmer maintaining dup2 wants to change the parameter names as part of working on the function's implementation, doing so is not a problem, whereas with named arguments, it would break code. Personally, I don't think that named arguments provide much value, and I _really_ don't want parameters to become part of the API. We have enough bikeshedding over names as it is and don't need to introduce yet more ways that changing libraries can break existing code. Unfortunately, given Walter's current position on this, I'm likely going to have to deal with named arguments and the problems that they bring, but I really don't have much good to say about them, and I do not look forward to having to deal with them in the least. - Jonathan M Davis
I agree. I know there are complaints about being required to use a particular tool to use a language, but this particular argument for named parameters uses a language change - one with big side effects - to do something that should be done by an IDE. The nice thing about proper editor support is that it continues to work exactly as expected even if you do change the parameter names in the library.
Feb 19
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Wednesday, 19 February 2020 at 19:34:53 UTC, bachmeier wrote:
 On Wednesday, 19 February 2020 at 19:13:01 UTC, Jonathan M 
 Davis wrote:
 [...]
I agree. I know there are complaints about being required to use a particular tool to use a language, but this particular argument for named parameters uses a language change - one with big side effects - to do something that should be done by an IDE. The nice thing about proper editor support is that it continues to work exactly as expected even if you do change the parameter names in the library.
What editor are you specifically talking about here and how should it be done? Generating comments like this? go(\*a*\ 1); Alex
Feb 19
parent reply Panke <tobias pankrath.net> writes:
On Wednesday, 19 February 2020 at 19:57:06 UTC, 12345swordy wrote:
 On Wednesday, 19 February 2020 at 19:34:53 UTC, bachmeier wrote:
 On Wednesday, 19 February 2020 at 19:13:01 UTC, Jonathan M 
 Davis wrote:
 [...]
I agree. I know there are complaints about being required to use a particular tool to use a language, but this particular argument for named parameters uses a language change - one with big side effects - to do something that should be done by an IDE. The nice thing about proper editor support is that it continues to work exactly as expected even if you do change the parameter names in the library.
What editor are you specifically talking about here and how should it be done? Generating comments like this? go(\*a*\ 1); Alex
E.g. CLion does it. In renders the parameter names at the call site without changing the code at all (it does not insert comments). It is a very useful feature. Granted, if that support was readily available for D than the argument for named parameters would be weaker.
Feb 19
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Wednesday, 19 February 2020 at 20:04:56 UTC, Panke wrote:
 On Wednesday, 19 February 2020 at 19:57:06 UTC, 12345swordy 
 wrote:
 On Wednesday, 19 February 2020 at 19:34:53 UTC, bachmeier 
 wrote:
 [...]
What editor are you specifically talking about here and how should it be done? Generating comments like this? go(\*a*\ 1); Alex
E.g. CLion does it. In renders the parameter names at the call site without changing the code at all (it does not insert comments). It is a very useful feature. Granted, if that support was readily available for D than the argument for named parameters would be weaker.
Isn't that mainly due to cpp having header files? -Alex
Feb 19
next sibling parent Arine <arine123445128843 gmail.com> writes:
On Wednesday, 19 February 2020 at 20:09:25 UTC, 12345swordy wrote:
 On Wednesday, 19 February 2020 at 20:04:56 UTC, Panke wrote:
 On Wednesday, 19 February 2020 at 19:57:06 UTC, 12345swordy 
 wrote:
 On Wednesday, 19 February 2020 at 19:34:53 UTC, bachmeier 
 wrote:
 [...]
What editor are you specifically talking about here and how should it be done? Generating comments like this? go(\*a*\ 1); Alex
E.g. CLion does it. In renders the parameter names at the call site without changing the code at all (it does not insert comments). It is a very useful feature. Granted, if that support was readily available for D than the argument for named parameters would be weaker.
Isn't that mainly due to cpp having header files? -Alex
parameter names, rather than the names being embedded in the code. So not really limited to header files.
Feb 19
prev sibling parent Panke <tobias pankrath.net> writes:
On Wednesday, 19 February 2020 at 20:09:25 UTC, 12345swordy wrote:
 Isn't that mainly due to cpp having header files?

 -Alex
It displays the argument names where the function is used, so I see no connection to header files.
Feb 20
prev sibling next sibling parent Panke <tobias pankrath.net> writes:
On Wednesday, 19 February 2020 at 19:13:01 UTC, Jonathan M Davis 
wrote:
 On Wednesday, February 19, 2020 8:31:00 AM MST Yuxuan Shui via

 Named arguments are completely unnecessary in such a situation. 
 The list of arguments is short enough that it's trivial to know 
 which is which and what they're for. Having the parameter names 
 listed at the call site is just unnecessary cruft, and having 
 named arguments in the language opens up the whole issue of 
 whether the names src and dst were the best names for dup2.
I just can say that my professional experience leads me to believe the complete opposite. Named parameters and parameter names at the call site are useful, aid in understanding the code and prevent bugs.
Feb 19
prev sibling parent Meta <jared771 gmail.com> writes:
On Wednesday, 19 February 2020 at 19:13:01 UTC, Jonathan M Davis 
wrote:
 On Wednesday, February 19, 2020 8:31:00 AM MST Yuxuan Shui via 
 Digitalmars-d wrote:
 On Friday, 7 February 2020 at 03:33:26 UTC, Jonathan M Davis

 wrote:
 but for the most part, they're useful because a function has 
 way too many parameters, in which case, the function should 
 have been designed differently.
Named parameters are not just for when there are too many parameters. Easy example: dup2(a, b); vs dup2(src: a, dst: b);
Named arguments are completely unnecessary in such a situation. The list of arguments is short enough that it's trivial to know which is which and what they're for.
This is off the mark. Named arguments are very useful even in this case (maybe *especially* in this case, when you have to rely on the convention that src always comes first and dst always comes second). I've been using Groovy a lot at work lately, which has support for named arguments (and interpolated strings, by the way), and it allows for writing some very clear and readable code.
Feb 20
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
Replying to Timon's post on the feedback thread:

On 2/6/20 10:49 PM, Timon Gehr wrote:
 This introduces syntax like:

 import std.typecons;
 alias t=AliasSeq!(c:1, a:2, b:3); // valid according to DIP
 void foo(int a,int b,int c){
      writeln(a," ",b," ",c);
 }

 void main(){
      foo(t);
 }
Does it? AliasSeq's template parameter (singular) is named TList, not a, b, or c. So I would expect this to fail to compile. This does bring up a valid point though. The DIP talks about variadic parameters, but template variadic parameters actually have a name. So what does this mean? Is it valid? AliasSeq!(TList: 1, 2, 3) -Steve
Feb 06
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/7/20 12:00 AM, Steven Schveighoffer wrote:

 This does bring up a valid point though. The DIP talks about variadic 
 parameters, but template variadic parameters actually have a name.
So do typesafe variadics. I think the DIP needs to be more explicit here with what it means. -Steve
Feb 06
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07.02.20 06:00, Steven Schveighoffer wrote:
 Replying to Timon's post on the feedback thread:
 
 On 2/6/20 10:49 PM, Timon Gehr wrote:
  > This introduces syntax like:
  >
  > import std.typecons;
  > alias t=AliasSeq!(c:1, a:2, b:3); // valid according to DIP
  > void foo(int a,int b,int c){
  >      writeln(a," ",b," ",c);
  > }
  >
  > void main(){
  >      foo(t);
  > }
 
 Does it? AliasSeq's template parameter (singular) is named TList, not a, 
 b, or c.
 
 So I would expect this to fail to compile.
It does add the syntax, and I would argue it is not ideal if this fails to pass semantic analysis.
Feb 07
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/7/20 5:52 AM, Timon Gehr wrote:
 On 07.02.20 06:00, Steven Schveighoffer wrote:
 Replying to Timon's post on the feedback thread:

 On 2/6/20 10:49 PM, Timon Gehr wrote:
  > This introduces syntax like:
  >
  > import std.typecons;
  > alias t=AliasSeq!(c:1, a:2, b:3); // valid according to DIP
  > void foo(int a,int b,int c){
  >      writeln(a," ",b," ",c);
  > }
  >
  > void main(){
  >      foo(t);
  > }

 Does it? AliasSeq's template parameter (singular) is named TList, not 
 a, b, or c.

 So I would expect this to fail to compile.
It does add the syntax, and I would argue it is not ideal if this fails to pass semantic analysis.
Yes, it's valid syntax, but shouldn't pass semantic -- you named arguments that aren't present (AliasSeq does not have parameters named a b or c). But the DIP isn't 100% clear that named variadics cannot receive NamedParameter items. It says extra parameters match the "trailing ... of variadic parameter lists and Identifiers are not allowed". Not all variadic functions have a trailing ... without a name. I would think AliasSeq!(TList: 1, 2, 3) should be valid. -Steve
Feb 07
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07.02.20 16:28, Steven Schveighoffer wrote:
 It does add the syntax, and I would argue it is not ideal if this 
 fails to pass semantic analysis.
Yes, it's valid syntax, but shouldn't pass semantic -- you named arguments that aren't present (AliasSeq does not have parameters named a b or c). ...
So you are arguing that e.g., std.typecons.Proxy should fail to work with named arguments?
 But the DIP isn't 100% clear that named variadics cannot receive 
 NamedParameter items. It says extra parameters match the "trailing ... 
 of variadic parameter lists and Identifiers are not allowed". Not all 
 variadic functions have a trailing ... without a name. I would think 
 AliasSeq!(TList: 1, 2, 3) should be valid.
 
 -Steve
Why is that more useful than support for forwarding?
Feb 08
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/8/20 5:04 AM, Timon Gehr wrote:
 On 07.02.20 16:28, Steven Schveighoffer wrote:
 It does add the syntax, and I would argue it is not ideal if this 
 fails to pass semantic analysis.
Yes, it's valid syntax, but shouldn't pass semantic -- you named arguments that aren't present (AliasSeq does not have parameters named a b or c). ...
So you are arguing that e.g., std.typecons.Proxy should fail to work with named arguments?
Technically, it doesn't today, so it's not a break. But it is a good point. opDispatch in general will fail to support named parameters without a ton of extra mixins and boilerplate (potentially, you could have opDispatch specify all parameters and names).
 
 But the DIP isn't 100% clear that named variadics cannot receive 
 NamedParameter items. It says extra parameters match the "trailing ... 
 of variadic parameter lists and Identifiers are not allowed". Not all 
 variadic functions have a trailing ... without a name. I would think 
 AliasSeq!(TList: 1, 2, 3) should be valid.
Why is that more useful than support for forwarding?
Not more useful, but unambiguous. For example, what does AliasSeq!(TList: 1) mean? Did you mean to assign a 1 to the template parameter already named TList, or did you mean to submit a parameter named TList? Should this then fail to compile or pass? void foo(int a); alias params = AliasSeq!(TList: 1); foo(params); // does this mean foo(1) or foo(TList: 1)? Potentially, we could specify with some syntax that a parameter could consume all named arguments not already tagged, and that name wouldn't matter. An interesting artifact of this, is that we could potentially eliminate std.typecons.Tuple. But I feel this would be an additional proposal on top of named parameters, even though it's related. -Steve
Feb 08
parent Walter Bright <newshound2 digitalmars.com> writes:
It's clear that what should happen with named arguments and variadics is far 
from clear-cut. Therefore, the proper way forward for the time being is to 
simply disallow matching them with a ...

Nothing is being broken by this, as currently named arguments do not work at
all.

If a decent design for it is developed in the future, we can always add it. But 
adding a design now that turns out later to be inferior or botched is going to 
be hard to remove. Just look at the trouble we have with alias this and 
autodecoding.
Feb 08
prev sibling next sibling parent Fynn =?UTF-8?B?U2NocsO2ZGVy?= <fynnos live.com> writes:
On Thursday, 6 February 2020 at 06:08:59 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Community 
 Review for DIP 1030, "Named Arguments":
I think this DIP is a solid approach to named arguments for D. However, I second Timon's concern from the feedback thread regarding point 5
 If there are more NamedArguments than Parameters, the remainder 
 match the trailing ... of variadic parameter lists, and 
 Identifiers are not allowed.
Either leftover named arguments should go into the variadic parameters (and it must be able to tell whether a parameter in the list was given with an Identifier or not) OR a template could decide to catch leftover NamedArguments in another form of variadic named parameters (similar to Python's kwargs).
Feb 06
prev sibling next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Friday, 7 February 2020 at 20:02:18 UTC, Walter Bright wrote:
 [snip]

 So,

     void foo(int a, ...);

 called with:

     foo(b:1, 2)

 should be the equivalent of:

     foo(2, 1)

 ?
This was on the feedback thread, but I didn't want to pollute that... This reminds me of what **kwargs in Python is trying to address. Basically, the identifier b is dropped. For instance, foo(c:3, b:1, 2) would be equivalent to foo(2, 3, 1) under the DIP and the information that you might have wanted to use to make it actually foo(2, 1, 3) is no longer available.
Feb 07
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07.02.20 21:49, jmh530 wrote:
 On Friday, 7 February 2020 at 20:02:18 UTC, Walter Bright wrote:
 [snip]

 So,

     void foo(int a, ...);

 called with:

     foo(b:1, 2)

 should be the equivalent of:

     foo(2, 1)

 ?
This was on the feedback thread, but I didn't want to pollute that...
Here's my answer from the feedback thread: I was thinking about template variadics, not sure about the C-style ones. I think your example would not match in any case, because unnamed arguments after a named argument match the next parameter, so actually you don't provide a value for 'a'. Also, the name would have to be preserved through the template instantiation. void foo(T...)(int a, T args){ ... } foo(b: 1, a: 2) <=> foo!(b: int)(2, 1); Constructs like https://dlang.org/library/std/typecons/proxy.html should ideally not break.
Feb 08
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Wednesday, February 5, 2020 11:08:59 PM MST Mike Parker via Digitalmars-d
 wrote:
 This is the feedback thread for the first round of Community
 Review for DIP 1030, "Named Arguments":

 https://github.com/dlang/DIPs/blob/44b0d4ec0da6a2e797ede748fb1e81cd6db1037
 1/DIPs/DIP1030.md

 Here in the discussion thread, you are free to discuss anything
 and everything related to the DIP. Express your support or
 opposition, debate alternatives, argue the merits... in other
 words, business as usual.

 However, if you have any specific feedback for how to improve the
 the proposal itself, then please post it in the feedback thread.
 The feedback thread will be the source for the review summary I
 write at the end of this review round. I will post a link to that
 thread immediately following this post. Just be sure to read and
 understand the Reviewer Guidelines before posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 The review period will end at 11:59 PM ET on February 20, or when
 I make a post declaring it complete. Discussion in this thread
 may continue beyond that point.

 At the end of Round 1, if further review is deemed necessary, the
 DIP will be scheduled for another round of Community Review.
 Otherwise, it will be queued for the Final Review and Formal
 Assessment.

 Please stay on topic here. I will delete posts that are
 completely off topic.
Well, I'll say again that I don't like the idea of having named arguments in the language, because it makes the parameter names part of the API, resulting in yet more bikeshedding and yet another thing that can't be changed without breaking existing code. Once in a while, named arguments may be useful, but for the most part, they're useful because a function has way too many parameters, in which case, the function should have been designed differently. Unfortunately, since it's Walter who created the DIP, and a number of people do like the idea of named arguments, I expect that some form of this will make it in, but I still think that it's a bad idea. - Jonathan M Davis
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. Here's a thought, which I haven't considered how it interacts with this DIP deeply, but it should be on the table: I do an immense amount of generative meta; generate wrappers, shims, bindings etc, which wrap existing functions. When the parameter names become part of the API, it means any such meta must pay extra attention to properly mirror the parameter names, and it must also carefully mirror the default args from the function it's wrapping. While most of my code takes care to do this anyway, there are cases where it's unnecessary and inconvenient. Some tasks can be completed with a tool like: ReturnType!originalFunction wrapper(alias originalFunction)(Parameters!originalFunction args) { // special sauce... return originalFunction(args); } It is possible to write many forms of glue this way. If we must mirror the argument names and default arguments, you must fall back into string mixin territory, and the code to emit the proper prototype is complex and intensive. In a named-arguments world, shim's like the one I showed above are no longer valid where calling code would use named arguments. I don't there is existing language that could make this possible: ReturnType!originalFunction wrapper(alias originalFunction)(ParametersWithNamesAndDefaultArgs!originalFunction args) { ... } For me to get excited about this DIP sufficiently to offset my fears, I need to know what it's for... and I don't. If it's useful in the rare case where functions have way too many parameters... personally, I resolve that by making my functions NOT have way too many parameters. I'm not sure that too-many-parameters is a pattern that should be encouraged by the core language. I would not to do this unless we can provide a really compelling case to support its existence. I'm not satisfied that case exists here. Maybe I missed it? (I'm not really following this topic)
Feb 10
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 If we must mirror
 the argument names and default arguments, you must fall back 
 into string mixin territory
It is super simple. Consider this example: --- int foo(string s = null, int a = 12) { return a + 12; } template wrapWithPrint(alias fn) { static if(is(typeof(fn) P == __parameters)) auto wrapWithPrint(P params) { import std.stdio; writeln(params); auto ret = fn(params); writeln("returned: ", ret); return ret; } else static assert(0); } void main() { wrapWithPrint!foo(); wrapWithPrint!foo("cool"); wrapWithPrint!foo("cool", 20); } --- Default values and param names are included in the __parameters thing and just works if you use it directly. I saw people overcomplicating this just a few hours ago too which is why I have this example ready. There's plenty of techniques to do this though I guess they aren't well known.
Feb 10
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10.02.20 20:46, Adam D. Ruppe wrote:
 On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 If we must mirror
 the argument names and default arguments, you must fall back into 
 string mixin territory
It is super simple. Consider this example: --- int foo(string s = null, int a = 12) {         return a + 12; } template wrapWithPrint(alias fn) {         static if(is(typeof(fn) P == __parameters))         auto wrapWithPrint(P params) {                 import std.stdio;                 writeln(params);                 auto ret = fn(params);                 writeln("returned: ", ret);                 return ret;         }         else static assert(0); } void main() {         wrapWithPrint!foo();         wrapWithPrint!foo("cool");         wrapWithPrint!foo("cool", 20); } --- Default values and param names are included in the __parameters thing and just works if you use it directly. I saw people overcomplicating this just a few hours ago too which is why I have this example ready. There's plenty of techniques to do this though I guess they aren't well known.
What if fn is a template?
Feb 11
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 11 February 2020 at 09:02:03 UTC, Timon Gehr wrote:
 What if fn is a template?
Then, as I'm sure you already know, it won't work. It needs an instantiation to wrap in this style. Same with Manu's code though so we've lost nothing. Can be slightly annoying with stuff like `to!int`, you'd have to `wrap!(to!it)...` A generic forwarder would be variadic and thus this DIP doesn't apply to it regardless. (Though, in a previous review on github for this I proposed a way to handle that - make a variadic template with named params form an anonymous struct that the receiving template can process. Similar to Python's kwargs I'm told. Got pushback and I decided to table it, even though it would provide a lot of cool flexibility so hoping we can come back to it later.)
Feb 11
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/11/20 8:56 AM, Adam D. Ruppe wrote:
 On Tuesday, 11 February 2020 at 09:02:03 UTC, Timon Gehr wrote:
 What if fn is a template?
Then, as I'm sure you already know, it won't work. It needs an instantiation to wrap in this style. Same with Manu's code though so we've lost nothing.
Manu's example doesn't work, but this would (and I use this all the time): auto wrapper(alias originalFunction, T...)(T args) if (...) // makes sure we can call the function { return originalFunction(args); }
 Can be slightly annoying with stuff like `to!int`, you'd have to 
 `wrap!(to!it)...`
 
 A generic forwarder would be variadic and thus this DIP doesn't apply to 
 it regardless. (Though, in a previous review on github for this I 
 proposed a way to handle that - make a variadic template with named 
 params form an anonymous struct that the receiving template can process. 
 Similar to Python's kwargs I'm told. Got pushback and I decided to table 
 it, even though it would provide a lot of cool flexibility so hoping we 
 can come back to it later.)
What if fn has 10 different overloads? You have to provide all of them. Where as a template forwarder as above just works. I think we need to solve this problem in a "just works" way before having named parameters. -Steve
Feb 11
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 11 February 2020 at 14:22:30 UTC, Steven 
Schveighoffer wrote:
 Manu's example doesn't work, but this would (and I use this all 
 the time):

 auto wrapper(alias originalFunction, T...)(T args) if (...) //
Yeah, I use that a lot too.
 What if fn has 10 different overloads?
static foreach(overload; __traits(getOverloads, item, fun)) static if(is(typeof(overload) Params == __parameters)) auto wrap(Params p) { return overload(p); } Which has advantages over the T... in terms of error messages and future reflection. Also works in interfaces and similar. So I agree with you that the names in variadics would be super cool for lots of reasons. I'm meh on if it is *required* but I certainly do prefer it. Just still knowing these techniques are useful anyway so I take any chance to educate :)
Feb 11
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10.02.20 20:46, Adam D. Ruppe wrote:
 
 It is super simple. Consider this example:
 
 ---
 template wrapWithPrint(alias fn) {
          static if(is(typeof(fn) P == __parameters))
          auto wrapWithPrint(P params) {
                  import std.stdio;
                  writeln(params);
                  auto ret = fn(params);
                  writeln("returned: ", ret);
                  return ret;
          }
          else static assert(0);
 }
 ---
int troll(int ret){ return ret; } void main(){ wrapWithPrint!troll(2); }
Feb 11
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 11 February 2020 at 09:29:22 UTC, Timon Gehr wrote:
 int troll(int ret){ return ret; }

 void main(){
     wrapWithPrint!troll(2);
 }
lol, indeed. There can be downsides to inheriting random names :)
Feb 11
prev sibling next sibling parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 [...]
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. [...]
For me personalty, readability\reliability is a huge factor here. Knowing what values should go to where is a big plus for me, when to web development, and the default parameters prevent me sending values to the wrong parameter. -Alex
Feb 10
next sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Monday, 10 February 2020 at 19:49:24 UTC, 12345swordy wrote:
 On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 [...]
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. [...]
For me personalty, readability\reliability is a huge factor here. Knowing what values should go to where is a big plus for when it comes to web development, and the default parameters prevent me sending values to the wrong parameter. -Alex
Meant to say "Named arguments prevent me from sending values to the wrong parameter"
Feb 10
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On Mon, Feb 10, 2020 at 11:50 AM 12345swordy via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 [...]
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. [...]
For me personalty, readability\reliability is a huge factor here. Knowing what values should go to where is a big plus for me, when to web development, and the default parameters prevent me sending values to the wrong parameter. -Alex
That feels like a pretty washy justification. Do you have an answer to my actual criticisms? I feel like generative meta is one of D's biggest features and selling points, and making that very difficult feels like a material loss.
Feb 10
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Monday, 10 February 2020 at 20:45:22 UTC, Manu wrote:
 On Mon, Feb 10, 2020 at 11:50 AM 12345swordy via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 [...]
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. [...]
For me personalty, readability\reliability is a huge factor here. Knowing what values should go to where is a big plus for when it comes to web development, and the default parameters prevent me sending values to the wrong parameter. -Alex
That feels like a pretty washy justification.
Manu, it boils down to mainly experience when it comes to wanting named arguments. I have argue in favor of them in the past already in other DIP. I have no interest of repeating them.
Feb 10
parent reply Manu <turkeyman gmail.com> writes:
On Mon, Feb 10, 2020 at 1:05 PM 12345swordy via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 20:45:22 UTC, Manu wrote:
 On Mon, Feb 10, 2020 at 11:50 AM 12345swordy via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 [...]
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. [...]
For me personalty, readability\reliability is a huge factor here. Knowing what values should go to where is a big plus for when it comes to web development, and the default parameters prevent me sending values to the wrong parameter. -Alex
That feels like a pretty washy justification.
Manu, it boils down to mainly experience when it comes to wanting named arguments. I have argue in favor of them in the past already in other DIP. I have no interest of repeating them.
I've seen some arguments, but I haven't understood them personally. I don't have a feel for their value, I can't judge that. I have described an important material loss associated with this. I'd like to see that important issue addressed in the form of "use this pattern instead" or, "we accept we are abandoning that important pattern, we feel it was less important than this DIP, and we accept code that uses that pattern will be broken", which, incidentally, is almost all D code I've ever written in a professional capacity... :/ I also have a fear that where making parameter names part of the API; renaming parameter == breaking change, this feels bad to me. It's resistant to improving API clarity over time. In my experience, API clarity is an ongoing maintenance challenge, where your poor choice in names is only discovered some time later as you have experience with other humans sense of intuition differing from your own initial judgement. That argument is about equally washy as your core argument, except from my personal point of view, I know that my argument here absolutely applies to me frequently over decades of experience, while I've never wanted names arguments once; so weighing the value judgement in that particular compromise seems obvious to me.
Feb 10
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Monday, 10 February 2020 at 21:17:45 UTC, Manu wrote:
 On Mon, Feb 10, 2020 at 1:05 PM 12345swordy via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 20:45:22 UTC, Manu wrote:
 On Mon, Feb 10, 2020 at 11:50 AM 12345swordy via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 [...]
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. [...]
For me personalty, readability\reliability is a huge factor here. Knowing what values should go to where is a big plus code when it comes to web development, and the default parameters prevent me sending values to the wrong parameter. -Alex
That feels like a pretty washy justification.
Manu, it boils down to mainly experience when it comes to wanting named arguments. I have argue in favor of them in the past already in other DIP. I have no interest of repeating them.
I've seen some arguments, but I haven't understood them personally. I don't have a feel for their value, I can't judge that. I have described an important material loss associated with this. I'd like to see that important issue addressed in the form of "use this pattern instead" or, "we accept we are abandoning that important pattern, we feel it was less important than this DIP, and we accept code that uses that pattern will be broken", which, incidentally, is almost all D code I've ever written in a professional capacity... :/ I also have a fear that where making parameter names part of the API; renaming parameter == breaking change, this feels bad to me. It's resistant to improving API clarity over time. In my experience, API clarity is an ongoing maintenance challenge, where your poor choice in names is only discovered some time later as you have experience with other humans sense of intuition differing from your own initial judgement. That argument is about equally washy as your core argument, except from my personal point of view, I know that my argument here absolutely applies to me frequently over decades of experience, while I've never wanted names arguments once; so weighing the value judgement in that particular compromise seems obvious to me.
Yes, I have encounter the "API breakage" counter argument in other threads already. Still not convinced that it is a big issue as they make it out to be.
Feb 10
next sibling parent reply Manu <turkeyman gmail.com> writes:
On Mon, Feb 10, 2020 at 1:30 PM 12345swordy via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 21:17:45 UTC, Manu wrote:
 On Mon, Feb 10, 2020 at 1:05 PM 12345swordy via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 20:45:22 UTC, Manu wrote:
 On Mon, Feb 10, 2020 at 11:50 AM 12345swordy via
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 [...]
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. [...]
For me personalty, readability\reliability is a huge factor here. Knowing what values should go to where is a big plus code when it comes to web development, and the default parameters prevent me sending values to the wrong parameter. -Alex
That feels like a pretty washy justification.
Manu, it boils down to mainly experience when it comes to wanting named arguments. I have argue in favor of them in the past already in other DIP. I have no interest of repeating them.
I've seen some arguments, but I haven't understood them personally. I don't have a feel for their value, I can't judge that. I have described an important material loss associated with this. I'd like to see that important issue addressed in the form of "use this pattern instead" or, "we accept we are abandoning that important pattern, we feel it was less important than this DIP, and we accept code that uses that pattern will be broken", which, incidentally, is almost all D code I've ever written in a professional capacity... :/ I also have a fear that where making parameter names part of the API; renaming parameter == breaking change, this feels bad to me. It's resistant to improving API clarity over time. In my experience, API clarity is an ongoing maintenance challenge, where your poor choice in names is only discovered some time later as you have experience with other humans sense of intuition differing from your own initial judgement. That argument is about equally washy as your core argument, except from my personal point of view, I know that my argument here absolutely applies to me frequently over decades of experience, while I've never wanted names arguments once; so weighing the value judgement in that particular compromise seems obvious to me.
Yes, I have encounter the "API breakage" counter argument in other threads already. Still not convinced that it is a big issue as they make it out to be.
It's a huge problem today when a bad choice of function name is calcified; we'll be multiplying the probability of making bad naming choices by 2-3x. We can correct a bad function name by renaming it and producing a deprecated alias for the old name. We have no such way to correct a change in parameter name; we can't use alias because the parameter names are not part of the signature. Don't ignore the material issue I've shown that demands one of the 2 responses I suggested. If you push for acceptable of this DIP, then I think you must have a response to my primary issue.
Feb 10
next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Monday, 10 February 2020 at 21:41:02 UTC, Manu wrote:
 [snip]

 It's a huge problem today when a bad choice of function name is
 calcified; we'll be multiplying the probability of making bad 
 naming
 choices by 2-3x.
 We can correct a bad function name by renaming it and producing 
 a
 deprecated alias for the old name. We have no such way to 
 correct a
 change in parameter name; we can't use alias because the 
 parameter
 names are not part of the signature.

 Don't ignore the material issue I've shown that demands one of 
 the 2
 responses I suggested.
 If you push for acceptable of this DIP, then I think you must 
 have a
 response to my primary issue.
I was leaning towards favoring this DIP, as I frequently use named arguments in R and like the flexibility they offer in some cases. However, I came across two functions, written in python, at work. One takes a parameter and the other takes a slightly different parameter name. No good reason why these two do not use the same parameter names. They should be the same. However, python has named arguments for everything, so changing the names would mean that any code that uses the named version breaks. It definitely would make people much more conservative about changing their functions.
Feb 10
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 10 February 2020 at 21:54:53 UTC, jmh530 wrote:
 However, python has named arguments for everything, so changing 
 the names would mean that any code that uses the named version 
 breaks. It definitely would make people much more conservative 
 about changing their functions.
In Python it is different because there's no compiler to tell you where changes occur. In D, this is the most trivial type of breakage - the compiler tells you where the change is and can make a good guess as to what the fix is too and can suggest it. It is a slight hassle - I remember renaming of functions in std.string driving me nuts in D ~2012ish. But it never *broke* my code per se, it wasn't something throwing at runtime when it didn't before, it was just an annoying half hour of find/replace tedium when I chose to update. (and note an option was just to defer the update too) And now the names are legit better. Like I said earlier in the thread, I can see a middle-man wanting compatibility across versions being a maybe, and we could do a deprecated alias for that, but I doubt it will be that hard. Consider it a minor version bump and - in theory - updates should be easy enough to schedule and do that tedious find/replace.
Feb 10
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Monday, 10 February 2020 at 22:20:21 UTC, Adam D. Ruppe wrote:

 In D, this is the most trivial type of breakage - the compiler 
 tells you where the change is and can make a good guess as to 
 what the fix is too and can suggest it.
That's true, but it's an hell when involving libraries: an external library author changes a parameter names, and break not only your codebase, that you can easily fix, but also other external libraries, and so on. It's a cascade process.
Feb 11
parent reply Andrea Fontana <nospam example.com> writes:
On Tuesday, 11 February 2020 at 09:18:38 UTC, Paolo Invernizzi 
wrote:
 On Monday, 10 February 2020 at 22:20:21 UTC, Adam D. Ruppe 
 wrote:

 In D, this is the most trivial type of breakage - the compiler 
 tells you where the change is and can make a good guess as to 
 what the fix is too and can suggest it.
That's true, but it's an hell when involving libraries: an external library author changes a parameter names, and break not only your codebase, that you can easily fix, but also other external libraries, and so on. It's a cascade process.
If package dependencies are used correctly nothing is break :) Andrea
Feb 11
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Tuesday, 11 February 2020 at 09:27:52 UTC, Andrea Fontana 
wrote:
 On Tuesday, 11 February 2020 at 09:18:38 UTC, Paolo Invernizzi 
 wrote:
 On Monday, 10 February 2020 at 22:20:21 UTC, Adam D. Ruppe 
 wrote:

 In D, this is the most trivial type of breakage - the 
 compiler tells you where the change is and can make a good 
 guess as to what the fix is too and can suggest it.
That's true, but it's an hell when involving libraries: an external library author changes a parameter names, and break not only your codebase, that you can easily fix, but also other external libraries, and so on. It's a cascade process.
If package dependencies are used correctly nothing is break :) Andrea
What I mean, is that multiple authors can be involved in the necessary fix: it's not a matter of find/replace on your own codebase. Let's put It simple, and let's boil this down to essential: there's MORE probability of FUTURE breakage with named parameters, and that's a fact.
Feb 11
next sibling parent reply Arine <arine123445128843 gmail.com> writes:
On Tuesday, 11 February 2020 at 09:46:35 UTC, Paolo Invernizzi 
wrote:
 Let's put It simple, and let's boil this down to essential: 
 there's MORE probability of FUTURE breakage with named 
 parameters, and that's a fact.
Only if you use the feature. That's part of the reason why I don't think you should be able to set a default of the middle argument. This just forces someone to use the feature if they a default parameter in the middle without the rest that follow also having default values. Other than that, if you don't want your code to break potentially from argument changes, then don't use named parameters.
Feb 11
parent reply Manu <turkeyman gmail.com> writes:
On Tue, Feb 11, 2020 at 5:30 AM Arine via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Tuesday, 11 February 2020 at 09:46:35 UTC, Paolo Invernizzi
 wrote:
 Let's put It simple, and let's boil this down to essential:
 there's MORE probability of FUTURE breakage with named
 parameters, and that's a fact.
Only if you use the feature. That's part of the reason why I don't think you should be able to set a default of the middle argument. This just forces someone to use the feature if they a default parameter in the middle without the rest that follow also having default values. Other than that, if you don't want your code to break potentially from argument changes, then don't use named parameters.
As a library author, you can't control whether a client uses named arguments or not. You must assume that they might use them anywhere and everywhere. This is huge for phobos and druntime, which should have a major pass over all function argument names to achieve dignity before we set them in stone.
Feb 11
parent Arine <arine123445128843 gmail.com> writes:
On Tuesday, 11 February 2020 at 19:02:38 UTC, Manu wrote:
 On Tue, Feb 11, 2020 at 5:30 AM Arine via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 On Tuesday, 11 February 2020 at 09:46:35 UTC, Paolo Invernizzi 
 wrote:
 Let's put It simple, and let's boil this down to essential: 
 there's MORE probability of FUTURE breakage with named 
 parameters, and that's a fact.
Only if you use the feature. That's part of the reason why I don't think you should be able to set a default of the middle argument. This just forces someone to use the feature if they set a default parameter in the middle without the rest that follow also having default values. Other than that, if you don't want your code to break potentially from argument changes, then don't use named parameters.
As a library author, you can't control whether a client uses named arguments or not. You must assume that they might use them anywhere and everywhere. This is huge for phobos and druntime, which should have a major pass over all function argument names to achieve dignity before we set them in stone.
I meant that in terms of the user. A library author can choose what they want to do, they can break code just by changing the internal implementation that isn't exposed. Without changing the API. Ultimately you are at the mercy of the library author for basically everything anyways. If a library author doesn't take into consideration parameter names, the user can avoid breaking changes by simply not using them. Whether the author is right not to care about that can be debated, and whether it is their reponsibility. Anyways I agree, druntime and phobos names should be fixed, even if this DIP doesn't pass. Someone way back in the thread said something that I feel was overlooked. If this is only for readability, then creating a tool like in CLion seems like the better option. It'll have the same functionality (including the problem with template wrappers), won't burden library authors and you can opt in to use it. https://www.jetbrains.com/help/rider/Inline_Parameter_Name_Hints.html If you can get the desired effect without introducing a new feature, it should definitely be investigated. I also don't like that you can rearrange the parameters any which cause more problems trying to figure out which overload was called. The way it is currently written can make it more difficult to read code. I do want named parameters so that I don't have to write out all the default parameters just to get to use a different value for the last one. I can't think of a better solution than what he has, the way it is designed and used is simple. Named parameters would benefit it. https://github.com/ocornut/imgui/blob/v1.75/imgui.h#L451
Feb 13
prev sibling next sibling parent Claude <claudemr live.fr> writes:
On Tuesday, 11 February 2020 at 09:46:35 UTC, Paolo Invernizzi 
wrote:
 On Tuesday, 11 February 2020 at 09:27:52 UTC, Andrea Fontana 
 wrote:
 If package dependencies are used correctly nothing is break :)

 Andrea
What I mean, is that multiple authors can be involved in the necessary fix: it's not a matter of find/replace on your own codebase. Let's put It simple, and let's boil this down to essential: there's MORE probability of FUTURE breakage with named parameters, and that's a fact.
Yes, precisely... I was a bit circumspect about named arguments (coming from the C world, I don't use them, and don't feel the need to), and I was agreeing with Jonathan point of view. But I've changed my mind about it: I reckon naming things is quite important when writing a library. So that feature would make you think twice before naming a parameter, and care about how you name (and therefore design) things. So sure, it can break stuff, so that would probably be good if we could annotate parameter names with 'deprecated'. And replacing the awkward 'Flag' template is a nice plus. Therefore I'm all for that DIP (and we can probably wait later for a design working with variadic arguments).
Feb 11
prev sibling parent reply Andrea Fontana <nospam example.com> writes:
On Tuesday, 11 February 2020 at 09:46:35 UTC, Paolo Invernizzi 
wrote:
 Let's put It simple, and let's boil this down to essential: 
 there's MORE probability of FUTURE breakage with named 
 parameters, and that's a fact.
That's true for every dip we approve, not only for named paramaters.
Feb 11
parent Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Tuesday, 11 February 2020 at 14:05:08 UTC, Andrea Fontana 
wrote:
 On Tuesday, 11 February 2020 at 09:46:35 UTC, Paolo Invernizzi 
 wrote:
 Let's put It simple, and let's boil this down to essential: 
 there's MORE probability of FUTURE breakage with named 
 parameters, and that's a fact.
That's true for every dip we approve, not only for named paramaters.
No, there could be language improvements introduced with breaking changes, like the final-by-default that I endlessly put on the table as an example, that turns D into a language that's more resilient to breaking changes, on the contrary of named parameters.
Feb 11
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On Mon, Feb 10, 2020 at 1:55 PM jmh530 via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 21:41:02 UTC, Manu wrote:
 [snip]

 It's a huge problem today when a bad choice of function name is
 calcified; we'll be multiplying the probability of making bad
 naming
 choices by 2-3x.
 We can correct a bad function name by renaming it and producing
 a
 deprecated alias for the old name. We have no such way to
 correct a
 change in parameter name; we can't use alias because the
 parameter
 names are not part of the signature.

 Don't ignore the material issue I've shown that demands one of
 the 2
 responses I suggested.
 If you push for acceptable of this DIP, then I think you must
 have a
 response to my primary issue.
I was leaning towards favoring this DIP, as I frequently use named arguments in R and like the flexibility they offer in some cases. However, I came across two functions, written in python, at work. One takes a parameter and the other takes a slightly different parameter name. No good reason why these two do not use the same parameter names. They should be the same. However, python has named arguments for everything, so changing the names would mean that any code that uses the named version breaks. It definitely would make people much more conservative about changing their functions.
We deprecate and rename things all the time. If this DIP is accepted, I think it would be the case that we need a working pattern to deprecate argument names the same as we can with function names today. We can't use alias, because names are not part of the signature. We can't use overloads as backwards-compatibility wrappers, because they're ambiguous calls (again, because names are not pert of the signature). Calcification of API will increase. Poor name choices will be cemented in. On Mon, Feb 10, 2020 at 2:00 PM 12345swordy via Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 21:41:02 UTC, Manu wrote:
 It's a huge problem today when a bad choice of function name is
 calcified; we'll be multiplying the probability of making bad
 naming
 choices by 2-3x.
Which is a no big deal when the probability is very low to big with.
Ummm... you're saying bad API names has a "very low probability"? Finish this sentence: "There are 2 hard problems in computer science..." I mean, I'm constantly tweaking API's for intuitive appeal. Programmers do this _all the time_.
 We literally have two named arguments DIP that are postponed for
 this DIP. The discussion has been made so many times already in
 which your concerns and objections has brought up time and time
 again. Which frankly I don't have time nor the energy to argue in
 favor it again when you can look into those discussions threads
 already.
I've never posted a single comment in a named argument thread. It's just not a thing I care about. I commented today because I feel like this DIP has a high probability of acceptance (because Walter wrote it), and I wanted to understand what was about to happen. I'm still mostly ambivalent about this, but I'm concerned you're still carefully avoiding my key concern; I showed an entire class of code that will be broken, you need to have a response to that. Basically everything I've ever written in a professional capacity will cease working if clients can call with named arguments.

 named arguments.
They didn't have a decade of existing and important code that will break. I think accepting this DIP must be coupled with a recommended pattern to address the code I described, because it will be broken, and must be migrated. On Mon, Feb 10, 2020 at 2:10 PM Adam D. Ruppe via Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 20:50:40 UTC, Manu wrote:
 Not being able to easily produce call shims or wrappers is a
 huge loss without some sort of solution analogous to existing
 reflection tools.
This does not occur.
I don't understand... ?
Feb 10
next sibling parent aliak <something something.com> writes:
On Monday, 10 February 2020 at 23:48:05 UTC, Manu wrote:
 Ummm... you're saying bad API names has a "very low 
 probability"? Finish this sentence: "There are 2 hard problems 
 in computer science..."
Off by 1 errors? :)
 I mean, I'm constantly tweaking API's for intuitive appeal. 
 Programmers do this _all the time_.
Agreed. If it's any conciliation (i assume probably not but anyway), in swift you take a little bit more time to name things, but in my experience maintainability goes up 10x. Also, it has not really been an issue when doing scala or kotlin.
 We literally have two named arguments DIP that are postponed 
 for this DIP. The discussion has been made so many times 
 already in which your concerns and objections has brought up 
 time and time again. Which frankly I don't have time nor the 
 energy to argue in favor it again when you can look into those 
 discussions threads already.
I've never posted a single comment in a named argument thread. It's just not a thing I care about. I commented today because I feel like this DIP has a high probability of acceptance (because Walter wrote it), and I wanted to understand what was about to happen. I'm still mostly ambivalent about this, but I'm concerned you're still carefully avoiding my key concern; I showed an entire class of code that will be broken, you need to have a response to that. Basically everything I've ever written in a professional capacity will cease working if clients can call with named arguments.

 to named arguments.
They didn't have a decade of existing and important code that will break.
Feb 10
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 10 February 2020 at 23:48:05 UTC, Manu wrote:
 I showed an entire class of code that will be broken, you need 
 to have a response to that.
Take a look at how easy it is to write a full forwarder function: https://forum.dlang.org/post/cfcgecteoeynumsamjwe forum.dlang.org Note that the parameter names of the wrapper as seen from the outside (or even the inside if you fetch it off that tuple) are identical to the original. This has been defined in the language for years.
Feb 10
prev sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Monday, 10 February 2020 at 21:54:53 UTC, jmh530 wrote:
 On Monday, 10 February 2020 at 21:41:02 UTC, Manu wrote:
 [...]
I was leaning towards favoring this DIP, as I frequently use named arguments in R and like the flexibility they offer in some cases. However, I came across two functions, written in python, at work. One takes a parameter and the other takes a slightly different parameter name. No good reason why these two do not use the same parameter names. They should be the same.
<snip>
 However, python has named arguments for everything,
Nope: https://www.python.org/dev/peps/pep-0570/
Feb 20
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 20 February 2020 at 11:00:16 UTC, Atila Neves wrote:
 [snip]

 Nope: https://www.python.org/dev/peps/pep-0570/
1) Pep 570 is opt-in*. It gives you a bit more control so you can have positional-only and key-word only arguments. However, if you do not opt-in, then python still has a mixed of positional and named arguments for everything. See the standard_arg function in function examples: https://www.python.org/dev/peps/pep-0570/#function-examples In particular, I was thinking of situation where you have two functions def foo(arg1, arg2): def bar(arg1 other1): The following code is completely valid, both pre and post pep 570 foo(a, b) bar(a, b) foo(arg2=b, arg1=a) bar(other1=b, arg1=a) In my case, I was noticing that other1 is a lot like arg2, so you want to change other1's name to arg2. However, that will break the last line. Under pep 570, you could have instead written def foo(arg1, arg2, /): def bar(arg1 other1, /): and it won't break when you re-name it, but then you can't use the last two lines. Alternately, if try to use something like def foo(*, arg1, arg2): def bar(*, arg1 other1): then the first two lines calling foo and bar won't work. So even under pep 570, you would still be breaking code to re-name it. The problem comes from the standard method of mixing positional or keyword arguments. 2) Referring again to the pep 570 function examples, they have def combined_example(pos_only, /, mixed, *, kwd_only): where mixed (called standard in their example) is the mix of positional and keyword arguments. If D were to move in this direction, then we would have a similar function like void combined_example(Type1 pos_only, /, Type2 mixed, *, Type3 kwd_only) The only thing I would change is that pos_only should remain the default. So that would imply that the python function examples would instead be something like below in D. void standard_arg(Type1 pos_only) void mixed_arg(/, Type2 mixed) void kwd_only_arg(*, Type3 kwd_only) This would make named arguments opt-in and reduce the risk of people causing code breakage by changing APIs. One could start with just the mixed and consider adding the keyword only approach in the future if people want/need it. * That pep only was implemented in Python 3.8, which only came out in October of last year, I think I'm using 3.7 at work...so admittedly less familiar with it.
Feb 20
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Thursday, 20 February 2020 at 11:59:13 UTC, jmh530 wrote:
 On Thursday, 20 February 2020 at 11:00:16 UTC, Atila Neves 
 wrote:
 [snip]

 Nope: https://www.python.org/dev/peps/pep-0570/
1) Pep 570 is opt-in*. It gives you a bit more control so you can have positional-only and key-word only arguments. However, if you do not opt-in, then python still has a mixed of positional and named arguments for everything. See the standard_arg function in function examples:
That's the exact reason why they proposed 570: having named argument is not alway a win.
Feb 20
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Thursday, 20 February 2020 at 14:49:42 UTC, Paolo Invernizzi 
wrote:
 On Thursday, 20 February 2020 at 11:59:13 UTC, jmh530 wrote:
 On Thursday, 20 February 2020 at 11:00:16 UTC, Atila Neves 
 wrote:
 [snip]

 Nope: https://www.python.org/dev/peps/pep-0570/
1) Pep 570 is opt-in*. It gives you a bit more control so you can have positional-only and key-word only arguments. However, if you do not opt-in, then python still has a mixed of positional and named arguments for everything. See the standard_arg function in function examples:
That's the exact reason why they proposed 570: having named argument is not alway a win.
I don't think nor do I expect that people would used named arguments all the time when using another persons code. -Alex
Feb 20
next sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Thursday, 20 February 2020 at 15:34:31 UTC, 12345swordy wrote:
 On Thursday, 20 February 2020 at 14:49:42 UTC, Paolo Invernizzi 
 wrote:
 On Thursday, 20 February 2020 at 11:59:13 UTC, jmh530 wrote:
 On Thursday, 20 February 2020 at 11:00:16 UTC, Atila Neves 
 wrote:
 [snip]

 Nope: https://www.python.org/dev/peps/pep-0570/
1) Pep 570 is opt-in*. It gives you a bit more control so you can have positional-only and key-word only arguments. However, if you do not opt-in, then python still has a mixed of positional and named arguments for everything. See the standard_arg function in function examples:
That's the exact reason why they proposed 570: having named argument is not alway a win.
I don't think nor do I expect that people would used named arguments all the time when using another persons code. -Alex
*Unless it is mandate by the language obviously* -Alex
Feb 20
prev sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 20 February 2020 at 15:34:31 UTC, 12345swordy wrote:
 [snip]

 I don't think nor do I expect that people would used named 
 arguments all the time when using another persons code.

 -Alex
What's that saying? If some code can be written, it will be written. Regardless, it's a problem even for your own code too. If you have a big code base that uses a mix of positional and keyword arguments, then changing the names of function parameters causes code to break.
Feb 20
parent 12345swordy <alexanderheistermann gmail.com> writes:
On Thursday, 20 February 2020 at 15:51:57 UTC, jmh530 wrote:
 On Thursday, 20 February 2020 at 15:34:31 UTC, 12345swordy 
 wrote:
 [snip]

 I don't think nor do I expect that people would used named 
 arguments all the time when using another persons code.

 -Alex
What's that saying? If some code can be written, it will be written. Regardless, it's a problem even for your own code too. If you have a big code base that uses a mix of positional and keyword arguments, then changing the names of function parameters causes code to break.
Which it is trivial to fix, if you have right tools. -Alex
Feb 20
prev sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Monday, 10 February 2020 at 21:41:02 UTC, Manu wrote:
 On Mon, Feb 10, 2020 at 1:30 PM 12345swordy via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 21:17:45 UTC, Manu wrote:
 On Mon, Feb 10, 2020 at 1:05 PM 12345swordy via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 20:45:22 UTC, Manu wrote:
 On Mon, Feb 10, 2020 at 11:50 AM 12345swordy via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 [...]
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. [...]
For me personalty, readability\reliability is a huge factor here. Knowing what values should go to where is a big plus for me, when dealing with default arguments. I the default parameters prevent me sending values to the wrong parameter. -Alex
That feels like a pretty washy justification.
Manu, it boils down to mainly experience when it comes to wanting named arguments. I have argue in favor of them in the past already in other DIP. I have no interest of repeating them.
I've seen some arguments, but I haven't understood them personally. I don't have a feel for their value, I can't judge that. I have described an important material loss associated with this. I'd like to see that important issue addressed in the form of "use this pattern instead" or, "we accept we are abandoning that important pattern, we feel it was less important than this DIP, and we accept code that uses that pattern will be broken", which, incidentally, is almost all D code I've ever written in a professional capacity... :/ I also have a fear that where making parameter names part of the API; renaming parameter == breaking change, this feels bad to me. It's resistant to improving API clarity over time. In my experience, API clarity is an ongoing maintenance challenge, where your poor choice in names is only discovered some time later as you have experience with other humans sense of intuition differing from your own initial judgement. That argument is about equally washy as your core argument, except from my personal point of view, I know that my argument here absolutely applies to me frequently over decades of experience, while I've never wanted names arguments once; so weighing the value judgement in that particular compromise seems obvious to me.
Yes, I have encounter the "API breakage" counter argument in other threads already. Still not convinced that it is a big issue as they make it out to be.
It's a huge problem today when a bad choice of function name is calcified; we'll be multiplying the probability of making bad naming choices by 2-3x.
Which is a no big deal when the probability is very low to big with. Besides I don't need to justified it to you when are not the person who I need to be convinced in order for the dip to be accepted. We literally have two named arguments DIP that are postponed for this DIP. The discussion has been made so many times already in which your concerns and objections has brought up time and time again. Which frankly I don't have time nor the energy to argue in favor it again when you can look into those discussions threads already. named arguments. -Alex
Feb 10
prev sibling parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Monday, 10 February 2020 at 21:29:41 UTC, 12345swordy wrote:

 Yes, I have encounter the "API breakage" counter argument in 
 other threads already. Still not convinced that it is a big 
 issue as they make it out to be.
I don't know since when you are around in D-land, but I'm here since pre-1.0. Not ad hominem, but believe me, I think it's difficult to understand the immane efforts to convince the leadership that breakage for a solid reason is not an evil thing. The pendulum is waving between "breakage is not even taken in account" to "let's introduce more ways to have MORE breakage opportunity in the future". Maybe it's not a "bit issue" for someone, Walter included, but that's non sense, plain and simple. Until I will see a shift from 'virtual by default' to 'final by default' mentality, aka let's try to reduce FUTURE opportunity for breakage, I will push toward that direction. /P
Feb 11
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 11 February 2020 at 09:15:05 UTC, Paolo Invernizzi 
wrote:
 On Monday, 10 February 2020 at 21:29:41 UTC, 12345swordy wrote:

 Yes, I have encounter the "API breakage" counter argument in 
 other threads already. Still not convinced that it is a big 
 issue as they make it out to be.
I don't know since when you are around in D-land, but I'm here since pre-1.0. Not ad hominem, but believe me, I think it's difficult to understand the immane efforts to convince the leadership that breakage for a solid reason is not an evil thing. The pendulum is waving between "breakage is not even taken in account" to "let's introduce more ways to have MORE breakage opportunity in the future". Maybe it's not a "bit issue" for someone, Walter included, but that's non sense, plain and simple. Until I will see a shift from 'virtual by default' to 'final by default' mentality, aka let's try to reduce FUTURE opportunity for breakage, I will push toward that direction. /P
Then use cpp if you hate future code breakage that much. The appeal of d to me is that it is not afraid to break code if it turns out to be a bad idea or that the improvements outweigh the breakage. -Alex
Feb 11
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Tuesday, 11 February 2020 at 14:22:48 UTC, 12345swordy wrote:

 Then use cpp if you hate future code breakage that much.
I don't go down that rabbit hole ... I've seen it too many times here. I think I've exposed my complains on named parameters enough, and I think in a clear manner, so I will stop arguing here. But, as usual, I'm listening to argumentation, as I try to discuss to understand better a topic
Feb 11
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 11 February 2020 at 14:31:51 UTC, Paolo Invernizzi 
wrote:
 On Tuesday, 11 February 2020 at 14:22:48 UTC, 12345swordy wrote:

 Then use cpp if you hate future code breakage that much.
I don't go down that rabbit hole ... I've seen it too many times here.
What rabbit hole are you talking about here!? The cpp committee have religious like zeal when it comes to backwards compatibility. You want d to have that mentality as well? -Alex
Feb 11
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Tuesday, 11 February 2020 at 14:45:30 UTC, 12345swordy wrote:
 On Tuesday, 11 February 2020 at 14:31:51 UTC, Paolo Invernizzi 
 wrote:
 On Tuesday, 11 February 2020 at 14:22:48 UTC, 12345swordy 
 wrote:

 Then use cpp if you hate future code breakage that much.
I don't go down that rabbit hole ... I've seen it too many times here.
What rabbit hole are you talking about here!? The cpp committee have religious like zeal when it comes to backwards compatibility. You want d to have that mentality as well? -Alex
Probably I'm not able to explain myself clearly, so my fault ... let's try in this way. - I'm not against changing D language specifications or Phobos with breaking changes, on the contrary, I'm an historical baker of doing it also with _major_ breaking changes, in times where talking about "breaking customer code in ANY way" was an heresy :-P - Stated that, and coming back to named arguments, I prefer a language that encourage writing code that's difficult to break: virtual-by-default, for example, is against that principle. You should "explicitly" mark the methods that are parts of the API with virtual, turning encapsulation the default, and not the way round. - The fact that fields _names_ are already part of the API is _not_ an excuse to add more stuff like that, with named parameters. The "he is doing wrong, so I can do wrong as well" is not an argumentation (and add to that "I've never had complains on that in other languages") My reasoning is that, since months ago: a) breaking user codebase, in any way, was BAD b) so, a language feature that try to minimise (a) is GOOD c) but now, we want to improve the language, so we can _sometime_ go against rule (a) ... why rule (b) is not longer valid today? what is the _strong_ reason for turning D in a language _less_ robust to code refactories, encouraging a small and encapsulated API? please, be sure to reply only if the first part of the post is clear enough ... :-)
Feb 11
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 11 February 2020 at 15:05:48 UTC, Paolo Invernizzi 
wrote:
 On Tuesday, 11 February 2020 at 14:45:30 UTC, 12345swordy wrote:
 [...]
Probably I'm not able to explain myself clearly, so my fault ... let's try in this way. [...]
Then don't rename the arguments at all if you don't want to break userspace. Same principle goes to renaming functions. -Alex
Feb 11
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Tuesday, 11 February 2020 at 15:10:35 UTC, 12345swordy wrote:
 On Tuesday, 11 February 2020 at 15:05:48 UTC, Paolo Invernizzi 
 wrote:
 On Tuesday, 11 February 2020 at 14:45:30 UTC, 12345swordy 
 wrote:
 [...]
Probably I'm not able to explain myself clearly, so my fault ... let's try in this way. [...]
Then don't rename the arguments at all if you don't want to break userspace. Same principle goes to renaming functions. -Alex
That's exactly the point. If you don't change anything, you break anything. The more you _can_ change _without_ breaking other code is proper encapsulation, and with this DIP the amount of things that you _can't_ change is just increasing. Named arguments _enlarge_ the amount of code that you are exposing and that you _can't_ change without breaking someone else code.
Feb 11
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 11 February 2020 at 15:26:41 UTC, Paolo Invernizzi 
wrote:
 On Tuesday, 11 February 2020 at 15:10:35 UTC, 12345swordy wrote:
 On Tuesday, 11 February 2020 at 15:05:48 UTC, Paolo Invernizzi 
 wrote:
 On Tuesday, 11 February 2020 at 14:45:30 UTC, 12345swordy 
 wrote:
 [...]
Probably I'm not able to explain myself clearly, so my fault ... let's try in this way. [...]
Then don't rename the arguments at all if you don't want to break userspace. Same principle goes to renaming functions. -Alex
That's exactly the point. If you don't change anything, you break anything. The more you _can_ change _without_ breaking other code is proper encapsulation, and with this DIP the amount of things that you _can't_ change is just increasing. Named arguments _enlarge_ the amount of code that you are exposing and that you _can't_ change without breaking someone else code.
If you find yourself in a situation that you end up renaming the arguments over and over again, then you got bigger issues to worry about besides named arguments. -Alex
Feb 11
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Tuesday, 11 February 2020 at 16:26:59 UTC, 12345swordy wrote:

 If you find yourself in a situation that you end up renaming 
 the arguments over and over again, then you got bigger issues 
 to worry about besides named arguments.

 -Alex
Ok, that's enough for me
Feb 11
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 11 February 2020 at 16:37:20 UTC, Paolo Invernizzi 
wrote:
 On Tuesday, 11 February 2020 at 16:26:59 UTC, 12345swordy wrote:

 If you find yourself in a situation that you end up renaming 
 the arguments over and over again, then you got bigger issues 
 to worry about besides named arguments.

 -Alex
Ok, that's enough for me
opt-out of it. Breakage because of the function arguments has changed rarely happens in practice, and if it does happen, it is trivial to fix. I am going to be blunt on this, but some of the plausible scenarios being brought up is massively overblown to nonsense territory. One of the goals of Named Arguments is readability and so far no one has provided an alternative that is both useful and satisfactory to me. Opt-in named arguments? Makes the named arguments dead on arrival. -Alex
Feb 11
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 12/02/2020 6:46 AM, 12345swordy wrote:
 Opt-in named arguments? Makes the named arguments dead on arrival.
If you start with opt-in, you can make it the default later on without breaking code. If you start with as default you cannot make it opt-in without breaking code. To not consider an opt-in design is quite frankly over confident that other languages experiences will map 1:1 to D.
Feb 11
parent 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 11 February 2020 at 17:58:48 UTC, rikki cattermole 
wrote:
 On 12/02/2020 6:46 AM, 12345swordy wrote:
 Opt-in named arguments? Makes the named arguments dead on 
 arrival.
If you start with opt-in, you can make it the default later on without breaking code. If you start with as default you cannot make it opt-in without breaking code. To not consider an opt-in design is quite frankly over confident that other languages experiences will map 1:1 to D.
Yes, I remember and even participate in one of the dip that makes it opt-in. I consider that a terrible idea for reasons that I had already gave. -Alex
Feb 11
prev sibling next sibling parent reply IGotD- <nise nise.com> writes:
On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 I don't have any horse in this race... but I do just want to 
 echo that
 I don't understand this feature at all.
 I don't know what it's for. I've never felt I wanted named 
 arguments
It's about my thoughts too. I think the question that needs to be solved by named parameters isn't strong enough. Optional named parameters are handy but D already offers a variety of methods in order to pass those. My fear as already other people pointed out is that named arguments will give D split personality. Some people adore named arguments and will use them for everything and others will not touch them. Libraries will use either methods and therefore make D feel schizophrenic. Also what would the implementation complexity be if this would be implemented?
Feb 10
parent reply Manu <turkeyman gmail.com> writes:
On Mon, Feb 10, 2020 at 12:25 PM IGotD- via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 I don't have any horse in this race... but I do just want to
 echo that
 I don't understand this feature at all.
 I don't know what it's for. I've never felt I wanted named
 arguments
It's about my thoughts too. I think the question that needs to be solved by named parameters isn't strong enough. Optional named parameters are handy but D already offers a variety of methods in order to pass those. My fear as already other people pointed out is that named arguments will give D split personality. Some people adore named arguments and will use them for everything and others will not touch them. Libraries will use either methods and therefore make D feel schizophrenic. Also what would the implementation complexity be if this would be implemented?
I doubt there's any meaningful implementation complexity inside DMD. I showed examples of how this split personality will affect authors of meta libraries. Not being able to easily produce call shims or wrappers is a huge loss without some sort of solution analogous to existing reflection tools. I also think 'renaming a parameter (to improve API clarity) == breaking API change' is a frustrating world to live in.
Feb 10
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 10 February 2020 at 20:50:40 UTC, Manu wrote:
 Not being able to easily produce call shims or wrappers is a 
 huge loss without some sort of solution analogous to existing 
 reflection tools.
This does not occur.
Feb 10
prev sibling next sibling parent reply aliak <something something.com> writes:
On Monday, 10 February 2020 at 19:38:34 UTC, Manu wrote:
 On Thu, Feb 6, 2020 at 7:34 PM Jonathan M Davis via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On Wednesday, February 5, 2020 11:08:59 PM MST Mike Parker via 
 Digitalmars-d wrote:
 [...]
Well, I'll say again that I don't like the idea of having named arguments in the language, because it makes the parameter names part of the API, resulting in yet more bikeshedding and yet another thing that can't be changed without breaking existing code. Once in a while, named arguments may be useful, but for the most part, they're useful because a function has way too many parameters, in which case, the function should have been designed differently. Unfortunately, since it's Walter who created the DIP, and a number of people do like the idea of named arguments, I expect that some form of this will make it in, but I still think that it's a bad idea. - Jonathan M Davis
I don't have any horse in this race... but I do just want to echo that I don't understand this feature at all. I don't know what it's for. I've never felt I wanted named arguments personally, and Jonathan's criticism feels very real to me. Here's a thought, which I haven't considered how it interacts with this DIP deeply, but it should be on the table: I do an immense amount of generative meta; generate wrappers, shims, bindings etc, which wrap existing functions. When the parameter names become part of the API, it means any such meta must pay extra attention to properly mirror the parameter names, and it must also carefully mirror the default args from the function it's wrapping. While most of my code takes care to do this anyway, there are cases where it's unnecessary and inconvenient. Some tasks can be completed with a tool like: ReturnType!originalFunction wrapper(alias originalFunction)(Parameters!originalFunction args) { // special sauce... return originalFunction(args); }
Before the DIP you'd call that like: wrapper(1, 2, 3); After the DIP you'd call that like: wrapper(1, 2, 3); Or are you saying meta must mirror parameter names as well? If so why? You can't do the default args today anyway, and I'm not sure if it's ever been a problem? I do agree that having something like ParametersWithNamesAndDefaultArgs is infeasible. Not only from a technical point of view but maintenance, programming burden, and migratory.
Feb 10
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 11 February 2020 at 00:03:01 UTC, aliak wrote:
 I do agree that having something like 
 ParametersWithNamesAndDefaultArgs is infeasible.
I posted this earlier in this very thread: https://forum.dlang.org/post/cfcgecteoeynumsamjwe forum.dlang.org It is not only feasible... but trivial. ParametersWithNamesAndDefaultArgs is a *built-in language feature* - see 5.6 under here https://dlang.org/spec/expression.html#IsExpression Forwarding this stuff is not difficult at all.
Feb 10
next sibling parent reply aliak <something something.com> writes:
On Tuesday, 11 February 2020 at 00:40:58 UTC, Adam D. Ruppe wrote:
 On Tuesday, 11 February 2020 at 00:03:01 UTC, aliak wrote:
 I do agree that having something like 
 ParametersWithNamesAndDefaultArgs is infeasible.
I posted this earlier in this very thread: https://forum.dlang.org/post/cfcgecteoeynumsamjwe forum.dlang.org It is not only feasible... but trivial. ParametersWithNamesAndDefaultArgs is a *built-in language feature* - see 5.6 under here https://dlang.org/spec/expression.html#IsExpression Forwarding this stuff is not difficult at all.
Oh. Indeed :) Seems simple enough. But that darned __parameters thing. It's the devil. Reminded me of the first time I encountered that insomnia inducer, courtesy of H. S. Teoh (thanks HST) - https://forum.dlang.org/post/mailman.1565.1379620490.1719.digitalmars-d-learn puremagic.com
Feb 10
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Feb 11, 2020 at 12:58:23AM +0000, aliak via Digitalmars-d wrote:
[...]
 But that darned __parameters thing. It's the devil. Reminded me of the
 first time I encountered that insomnia inducer, courtesy of H. S. Teoh
 (thanks HST) -
 https://forum.dlang.org/post/mailman.1565.1379620490.1719.digitalmars-d-learn puremagic.com
Whoa. Just last week I was trying to look up this exact post, but couldn't, and now you show up with a convenient direct link to it. :-D Thanks!! And yeah, __parameters must be one of the darkest corners of D with the strangest, quirkiest semantics that anybody can imagine. It took me a LOT of trial-and-error and staring at Phobos code before I figured out that arcane black magic. (And even then, I'm still not 100% sure I got it all right...) T -- Life is complex. It consists of real and imaginary parts. -- YHL
Feb 10
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 11 February 2020 at 01:18:08 UTC, H. S. Teoh wrote:
 It took me a LOT of trial-and-error and staring at Phobos code 
 before I figured out that arcane black magic.
Getting individual pieces out of it need some techniques (gotta use the slice technique to get param UDAs too btw). It isn't bad once you know them, but yeah, you aren't going to magically know it without help. But doing it to *forward* like Manu wants is *very* easy. Then you just treat it as a single block and it ALL automatically just works! This isn't impossible, it isn't error-prone, it isn't even particularly verbose. It is just one thing to use.
Feb 10
prev sibling parent Manu <turkeyman gmail.com> writes:
On Mon, Feb 10, 2020 at 4:45 PM Adam D. Ruppe via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Tuesday, 11 February 2020 at 00:03:01 UTC, aliak wrote:
 I do agree that having something like
 ParametersWithNamesAndDefaultArgs is infeasible.
I posted this earlier in this very thread: https://forum.dlang.org/post/cfcgecteoeynumsamjwe forum.dlang.org It is not only feasible... but trivial. ParametersWithNamesAndDefaultArgs is a *built-in language feature* - see 5.6 under here https://dlang.org/spec/expression.html#IsExpression Forwarding this stuff is not difficult at all.
Sorry, I missed that above. Thanks for pointing this out. I did not realise __parameters populated the tuple with all that information... it's not even clear to me how that works! What manner of 'thing' exists in a tuple that can be a type, but also have a name and a default value associated with it? Whatever kind of thing the elements in the tuple are; this seems very useful, and I wanna know how to deploy this kind of thing generally. I don't even know what to call this... it's not a 'type' or a 'value', what 'kind of thing' is this? I guess it's a declaration alias. I wonder how this syntax is useful elsewhere...
Feb 10
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/10/20 2:38 PM, Manu wrote:
 I do an immense amount of generative meta; generate wrappers, shims,
 bindings etc, which wrap existing functions.
 When the parameter names become part of the API, it means any such
 meta must pay extra attention to properly mirror the parameter names,
 and it must also carefully mirror the default args from the function
 it's wrapping.
 While most of my code takes care to do this anyway, there are cases
 where it's unnecessary and inconvenient. Some tasks can be completed
 with a tool like:
 
    ReturnType!originalFunction wrapper(alias
 originalFunction)(Parameters!originalFunction args)
    {
      // special sauce...
      return originalFunction(args);
    }
 
 It is possible to write many forms of glue this way. If we must mirror
 the argument names and default arguments, you must fall back into
 string mixin territory, and the code to emit the proper prototype is
 complex and intensive.
 In a named-arguments world, shim's like the one I showed above are no
 longer valid where calling code would use named arguments.
This has convinced me (along with reading the subsequent thread) that we shouldn't introduce named parameters until we can solve this problem. Whether it be via Timon's suggestion of having template tuples capture named parameters or some other mechanism. And the is(typeof(fn) P == __parameters) idea isn't the right approach either. It intercepts the parameter names based on what the *target* is, not on how it was *called*. Templates make decisions based on what they are given. -Steve
Feb 11
prev sibling next sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 February 2020 at 06:08:59 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Community 
 Review for DIP 1030, "Named Arguments":

 https://github.com/dlang/DIPs/blob/44b0d4ec0da6a2e797ede748fb1e81cd6db10371/DIPs/DIP1030.md

 Here in the discussion thread, you are free to discuss anything 
 and everything related to the DIP. Express your support or 
 opposition, debate alternatives, argue the merits... in other 
 words, business as usual.

 However, if you have any specific feedback for how to improve 
 the the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary I write at the end of this review round. I will post a 
 link to that thread immediately following this post. Just be 
 sure to read and understand the Reviewer Guidelines before 
 posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 The review period will end at 11:59 PM ET on February 20, or 
 when I make a post declaring it complete. Discussion in this 
 thread may continue beyond that point.

 At the end of Round 1, if further review is deemed necessary, 
 the DIP will be scheduled for another round of Community 
 Review. Otherwise, it will be queued for the Final Review and 
 Formal Assessment.

 Please stay on topic here. I will delete posts that are 
 completely off topic.
I'm curious what the current state of druntime/phobos is with parameter name consistency. I took a quick look at std.math in phobos to see what some of the current argument names are: auto conj(Num)(Num z) safe pure nothrow nogc auto abs(Num)(Num x) nogc pure nothrow real cos(real x) safe pure nothrow nogc { pragma(inline, true); return core.math.cos(x); } auto sin(creal z) safe pure nothrow nogc auto sin(ireal y) safe pure nothrow nogc So we have some of this: conj(z:someValue); abs(x:someValue); sin(y:someValue); Now that parameter names are apart of the function's API, this inconsistency starts to matter as changing it breaks the API. Will druntime/phobos try to come up with standard names for these situations? Will we try to fix these names before integrating support for named parameters? If we need to change names later, what will the policy be for druntime/phobos for making parameter name changes when inconsistencies are discovered? Also consider the case when overloads use different parameter names. std.math.sin uses 'z' for creal arguments and 'y' for ireal arguments. This can cause issues during refactor as one needs to re-check all parameter names when changing types of arguments. i.e. sin(z:someValue); If you change the type of someValue from creal to ireal, then this would still call the creal overload, perhaps unexpectedly.
Feb 10
next sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Monday, 10 February 2020 at 23:20:34 UTC, Jonathan Marler 
wrote:
 On Thursday, 6 February 2020 at 06:08:59 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Community 
 Review for DIP 1030, "Named Arguments":

 https://github.com/dlang/DIPs/blob/44b0d4ec0da6a2e797ede748fb1e81cd6db10371/DIPs/DIP1030.md

 Here in the discussion thread, you are free to discuss 
 anything and everything related to the DIP. Express your 
 support or opposition, debate alternatives, argue the 
 merits... in other words, business as usual.

 However, if you have any specific feedback for how to improve 
 the the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary I write at the end of this review round. I will post a 
 link to that thread immediately following this post. Just be 
 sure to read and understand the Reviewer Guidelines before 
 posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 The review period will end at 11:59 PM ET on February 20, or 
 when I make a post declaring it complete. Discussion in this 
 thread may continue beyond that point.

 At the end of Round 1, if further review is deemed necessary, 
 the DIP will be scheduled for another round of Community 
 Review. Otherwise, it will be queued for the Final Review and 
 Formal Assessment.

 Please stay on topic here. I will delete posts that are 
 completely off topic.
I'm curious what the current state of druntime/phobos is with parameter name consistency. I took a quick look at std.math in phobos to see what some of the current argument names are: auto conj(Num)(Num z) safe pure nothrow nogc auto abs(Num)(Num x) nogc pure nothrow real cos(real x) safe pure nothrow nogc { pragma(inline, true); return core.math.cos(x); } auto sin(creal z) safe pure nothrow nogc auto sin(ireal y) safe pure nothrow nogc So we have some of this: conj(z:someValue); abs(x:someValue); sin(y:someValue); Now that parameter names are apart of the function's API, this inconsistency starts to matter as changing it breaks the API. Will druntime/phobos try to come up with standard names for these situations? Will we try to fix these names before integrating support for named parameters? If we need to change names later, what will the policy be for druntime/phobos for making parameter name changes when inconsistencies are discovered? Also consider the case when overloads use different parameter names. std.math.sin uses 'z' for creal arguments and 'y' for ireal arguments. This can cause issues during refactor as one needs to re-check all parameter names when changing types of arguments. i.e. sin(z:someValue); If you change the type of someValue from creal to ireal, then this would still call the creal overload, perhaps unexpectedly.
I took some time to go through the "std.array" module to see how many potential issues it might have. Here's what I saw: ------------------------------------------------------------------------------- different overloads of split use different parameter names -------------------------------------------------------------------------------
 S[] split(S)(S s)  safe pure
 auto split(alias isTerminator, Range)(Range range)
 auto split(Range, Separator)(Range range, Separator sep)
split(s: value); split(range: value); ------------------------------------------------------------------------------- different overloads of "array" use different parameter names -------------------------------------------------------------------------------
 ForeachType!Range[] array(Range)(Range r)
 ForeachType!(PointerTarget!Range)[] array(Range)(Range r)
 CopyTypeQualifiers!(ElementType!String,dchar)[] 
 array(String)(scope String str)
array(r: value); array(str: value); ------------------------------------------------------------------------------- Generic Range parameters use many different names 'r', 'range', 'ror', 'stuff', 's' -------------------------------------------------------------------------------
 auto split(alias isTerminator, Range)(Range range)
 ForeachType!Range[] array(Range)(Range r)
 ForeachType!(PointerTarget!Range)[] array(Range)(Range r)
 ElementEncodingType!(ElementType!RoR)[] join(RoR, R)(RoR ror, 
 scope R sep)
 ElementEncodingType!(ElementType!RoR)[] join(RoR, E)(RoR ror, 
 scope E sep)
 ElementEncodingType!(ElementType!RoR)[] join(RoR)(RoR ror)
 T[] replace(T, Range)(T[] subject, size_t from, size_t to, 
 Range stuff)
 ElementType!S[] replicate(S)(S s, size_t n)
split(r: value); array(range: value); join(ror: value); replace(subject: value1, from: value2, to: value3, stuff: value4); replicate(s: value, n: 100); ------------------------------------------------------------------------------- functions that take 2 arguments but have different parameter names -------------------------------------------------------------------------------
 CommonType!(T[], U[]) overlap(T, U)(T[] a, U[] b)  trusted
 pure nothrow bool sameHead(T)(in T[] lhs, in T[] rhs)
 pure nothrow bool sameTail(T)(in T[] lhs, in T[] rhs)
overlay(a: value1, b: value2); sameHead(lhs: value1, rhs: value2); ------------------------------------------------------------------------------- sometimes an array is passed with 'a', sometimes with 'array', sometimes 'arr' -------------------------------------------------------------------------------
 void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
 auto staticArray(size_t n, T)(scope T a)
 auto staticArray(size_t n, T)(scope T a, out size_t rangeLength)
 Appender!(E[]) appender(A : E[], E)(auto ref A array)
 RefAppender!(E[]) appender(P : E[]*, E)(P arrayPtr)
 struct Appender(A)
     this(A arr)  trusted pure nothrow
insertInPlace(array: value1, pos: value2, stuff: value3); staticArray(a: value); Appender(arr: value); ------------------------------------------------------------------------------- Appender functions use inconsistent parameter names -------------------------------------------------------------------------------
 struct Appender(A)
     void reserve(size_t newCapacity)
     private void ensureAddable(size_t nelems)
appender.reserve(newCapacity: value); appender.ensureAddable(nelems: value); ------------------------------------------------------------------------------- Sometimes "length" is spelled out, sometimes it is abbreviated to "len" -------------------------------------------------------------------------------
 auto staticArray(size_t n, T)(scope T a, out size_t rangeLength)
 private size_t appenderNewCapacity(size_t TSizeOf)(size_t 
 curLen, size_t reqLen)  safe pure nothrow
staticArray(a: value, rangeLength: value2); appenderNewCapacity(curLen: 100, reqLen: 200); ------------------------------------------------------------------------------- appender overloads use different parameter names -------------------------------------------------------------------------------
 Appender!(E[]) appender(A : E[], E)(auto ref A array)
 RefAppender!(E[]) appender(P : E[]*, E)(P arrayPtr)
appender(array: value); appender(arrayPtr: value);
Feb 10
parent Manu <turkeyman gmail.com> writes:
On Mon, Feb 10, 2020 at 4:05 PM Jonathan Marler via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Monday, 10 February 2020 at 23:20:34 UTC, Jonathan Marler
 wrote:
 On Thursday, 6 February 2020 at 06:08:59 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Community
 Review for DIP 1030, "Named Arguments":

 https://github.com/dlang/DIPs/blob/44b0d4ec0da6a2e797ede748fb1e81cd6db10371/DIPs/DIP1030.md

 Here in the discussion thread, you are free to discuss
 anything and everything related to the DIP. Express your
 support or opposition, debate alternatives, argue the
 merits... in other words, business as usual.

 However, if you have any specific feedback for how to improve
 the the proposal itself, then please post it in the feedback
 thread. The feedback thread will be the source for the review
 summary I write at the end of this review round. I will post a
 link to that thread immediately following this post. Just be
 sure to read and understand the Reviewer Guidelines before
 posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 The review period will end at 11:59 PM ET on February 20, or
 when I make a post declaring it complete. Discussion in this
 thread may continue beyond that point.

 At the end of Round 1, if further review is deemed necessary,
 the DIP will be scheduled for another round of Community
 Review. Otherwise, it will be queued for the Final Review and
 Formal Assessment.

 Please stay on topic here. I will delete posts that are
 completely off topic.
I'm curious what the current state of druntime/phobos is with parameter name consistency. I took a quick look at std.math in phobos to see what some of the current argument names are: auto conj(Num)(Num z) safe pure nothrow nogc auto abs(Num)(Num x) nogc pure nothrow real cos(real x) safe pure nothrow nogc { pragma(inline, true); return core.math.cos(x); } auto sin(creal z) safe pure nothrow nogc auto sin(ireal y) safe pure nothrow nogc So we have some of this: conj(z:someValue); abs(x:someValue); sin(y:someValue); Now that parameter names are apart of the function's API, this inconsistency starts to matter as changing it breaks the API. Will druntime/phobos try to come up with standard names for these situations? Will we try to fix these names before integrating support for named parameters? If we need to change names later, what will the policy be for druntime/phobos for making parameter name changes when inconsistencies are discovered? Also consider the case when overloads use different parameter names. std.math.sin uses 'z' for creal arguments and 'y' for ireal arguments. This can cause issues during refactor as one needs to re-check all parameter names when changing types of arguments. i.e. sin(z:someValue); If you change the type of someValue from creal to ireal, then this would still call the creal overload, perhaps unexpectedly.
I took some time to go through the "std.array" module to see how many potential issues it might have. Here's what I saw: ------------------------------------------------------------------------------- different overloads of split use different parameter names -------------------------------------------------------------------------------
 S[] split(S)(S s)  safe pure
 auto split(alias isTerminator, Range)(Range range)
 auto split(Range, Separator)(Range range, Separator sep)
split(s: value); split(range: value); ------------------------------------------------------------------------------- different overloads of "array" use different parameter names -------------------------------------------------------------------------------
 ForeachType!Range[] array(Range)(Range r)
 ForeachType!(PointerTarget!Range)[] array(Range)(Range r)
 CopyTypeQualifiers!(ElementType!String,dchar)[]
 array(String)(scope String str)
array(r: value); array(str: value); ------------------------------------------------------------------------------- Generic Range parameters use many different names 'r', 'range', 'ror', 'stuff', 's' -------------------------------------------------------------------------------
 auto split(alias isTerminator, Range)(Range range)
 ForeachType!Range[] array(Range)(Range r)
 ForeachType!(PointerTarget!Range)[] array(Range)(Range r)
 ElementEncodingType!(ElementType!RoR)[] join(RoR, R)(RoR ror,
 scope R sep)
 ElementEncodingType!(ElementType!RoR)[] join(RoR, E)(RoR ror,
 scope E sep)
 ElementEncodingType!(ElementType!RoR)[] join(RoR)(RoR ror)
 T[] replace(T, Range)(T[] subject, size_t from, size_t to,
 Range stuff)
 ElementType!S[] replicate(S)(S s, size_t n)
split(r: value); array(range: value); join(ror: value); replace(subject: value1, from: value2, to: value3, stuff: value4); replicate(s: value, n: 100); ------------------------------------------------------------------------------- functions that take 2 arguments but have different parameter names -------------------------------------------------------------------------------
 CommonType!(T[], U[]) overlap(T, U)(T[] a, U[] b)  trusted
 pure nothrow bool sameHead(T)(in T[] lhs, in T[] rhs)
 pure nothrow bool sameTail(T)(in T[] lhs, in T[] rhs)
overlay(a: value1, b: value2); sameHead(lhs: value1, rhs: value2); ------------------------------------------------------------------------------- sometimes an array is passed with 'a', sometimes with 'array', sometimes 'arr' -------------------------------------------------------------------------------
 void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
 auto staticArray(size_t n, T)(scope T a)
 auto staticArray(size_t n, T)(scope T a, out size_t rangeLength)
 Appender!(E[]) appender(A : E[], E)(auto ref A array)
 RefAppender!(E[]) appender(P : E[]*, E)(P arrayPtr)
 struct Appender(A)
     this(A arr)  trusted pure nothrow
insertInPlace(array: value1, pos: value2, stuff: value3); staticArray(a: value); Appender(arr: value); ------------------------------------------------------------------------------- Appender functions use inconsistent parameter names -------------------------------------------------------------------------------
 struct Appender(A)
     void reserve(size_t newCapacity)
     private void ensureAddable(size_t nelems)
appender.reserve(newCapacity: value); appender.ensureAddable(nelems: value); ------------------------------------------------------------------------------- Sometimes "length" is spelled out, sometimes it is abbreviated to "len" -------------------------------------------------------------------------------
 auto staticArray(size_t n, T)(scope T a, out size_t rangeLength)
 private size_t appenderNewCapacity(size_t TSizeOf)(size_t
 curLen, size_t reqLen)  safe pure nothrow
staticArray(a: value, rangeLength: value2); appenderNewCapacity(curLen: 100, reqLen: 200); ------------------------------------------------------------------------------- appender overloads use different parameter names -------------------------------------------------------------------------------
 Appender!(E[]) appender(A : E[], E)(auto ref A array)
 RefAppender!(E[]) appender(P : E[]*, E)(P arrayPtr)
appender(array: value); appender(arrayPtr: value);
Mmmm, wow. Yeah, it seems an important pre-req for this DIP to be accepted is that all standard libraries should have a major pass to make sure all parameter names are dignified names that we can confidently stand behind for the rest of time, and also that standard names for common parameters are decided and proliferated. "There are 2 hard problems in computer science..."
Feb 10
prev sibling next sibling parent Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Monday, 10 February 2020 at 23:20:34 UTC, Jonathan Marler 
wrote:
 Now that parameter names are apart of the function's API,
I'm not sure it's correct to say this, considering that parameter names have already been accessible using reflection for a while now. This is what allowed library implementations of named arguments to work. As such, effectively this DIP just adds some syntax sugar.
Feb 10
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/10/2020 3:20 PM, Jonathan Marler wrote:
   I took a quick look at std.math in phobos to see what some of the current 
 argument names are:
 
 auto conj(Num)(Num z)  safe pure nothrow  nogc
 auto abs(Num)(Num x)  nogc pure nothrow
 real cos(real x)  safe pure nothrow  nogc { pragma(inline, true); return 
 core.math.cos(x); }
 auto sin(creal z)  safe pure nothrow  nogc
 auto sin(ireal y)  safe pure nothrow  nogc
 
 So we have some of this:
 
 conj(z:someValue);
 abs(x:someValue);
 sin(y:someValue);
 
 Now that parameter names are apart of the function's API, this inconsistency 
 starts to matter
It isn't inconsistent. In math, z=x+iy is normal notation, i.e. x for real numbers, y for imaginary, and z for complex. Besides, I doubt there's much of any point for using named parameters for those functions.
Feb 10
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Tuesday, 11 February 2020 at 07:04:34 UTC, Walter Bright wrote:
 On 2/10/2020 3:20 PM, Jonathan Marler wrote:
   I took a quick look at std.math in phobos to see what some 
 of the current argument names are:
 
 auto conj(Num)(Num z)  safe pure nothrow  nogc
 auto abs(Num)(Num x)  nogc pure nothrow
 real cos(real x)  safe pure nothrow  nogc { pragma(inline, 
 true); return core.math.cos(x); }
 auto sin(creal z)  safe pure nothrow  nogc
 auto sin(ireal y)  safe pure nothrow  nogc
 
 So we have some of this:
 
 conj(z:someValue);
 abs(x:someValue);
 sin(y:someValue);
 
 Now that parameter names are apart of the function's API, this 
 inconsistency starts to matter
It isn't inconsistent. In math, z=x+iy is normal notation, i.e. x for real numbers, y for imaginary, and z for complex.
conj and abs are using template parameters. So if you're passing an imaginary number to conj you use "z", abs you use "x", and sin you use "y". ireal i; conj(z: i); abs(x: i); sin(y: i);
 Besides, I doubt there's much of any point for using named 
 parameters for those functions.
True. I estimate around 75% of functions in general don't benefit from named parameters. So the question becomes, what do we do about parameter name inconsistency in these cases for the standard libraries? If we don't think named parameters are useful for a function, will we leave them be? If so, can we come up with a criteria we can use to determine when named parameters make sense? I think this would help greatly in this transition to named parameters to help avoid alot of the bikeshedding I see coming when this is enabled. I was also hoping to get some answers from the leadership to the other questions:
 Will druntime/phobos try to come up with standard names for 
 these situations?
For example, for math functions like the ones I mentioned, are we going to normalize on "x", "y" and "z" depending on the type? And if it's a template that could accept any type, what name would we use in that case? Of course, if the answer to the previous question is that we won't bother with functions that don't make sense with named parameters, then this is a bad example. But the question still stands for functions that do make sense, do you think we should come up with a standard set of names to promote consistency accross the standard libraries, and 3rd party libraries? Also these questions:
 Will we try to fix these names before integrating support for 
 named parameters?
 If we need to change names later, what will the policy be for 
 druntime/phobos for making parameter name changes when 
 inconsistencies are discovered?
Also came up with another question looking through some of the external function declarations in druntime like the ones in https://github.com/dlang/druntime/blob/master/src/core/sys/windows/winbase.d It looks like the parameter names have been stripped out for the windows functions. Do you think we should add parameter names in those functions? If we do want to add names, do you think we should we use the hungarian notation parameter names from windows, or no?
Feb 11
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 11 February 2020 at 15:26:42 UTC, Jonathan Marler 
wrote:
 On Tuesday, 11 February 2020 at 07:04:34 UTC, Walter Bright 
 wrote:
 On 2/10/2020 3:20 PM, Jonathan Marler wrote:
 Will druntime/phobos try to come up with standard names for 
 these situations?
For example, for math functions like the ones I mentioned, are we going to normalize on "x", "y" and "z" depending on the type? And if it's a template that could accept any type, what name would we use in that case? Of course, if the answer to the previous question is that we won't bother with functions that don't make sense with named parameters, then this is a bad example. But the question still stands for functions that do make sense, do you think we should come up with a standard set of names to promote consistency accross the standard libraries, and 3rd party libraries?
Here's a better example: functions like move and memcpy that take source and destination arguments. Currently, move uses 'source" and "target", but memcpy uses "s2" and "s1".
Feb 11
parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/11/2020 8:35 AM, Paul Backus wrote:
 Here's a better example: functions like move and memcpy that take source and 
 destination arguments. Currently, move uses 'source" and "target", but memcpy 
 uses "s2" and "s1".
The C99 Standard says: void *memcpy(void * restrict s1, const void * restrict s2, size_t n); which is what we will slavishly use for all Standard C library functions.
Feb 11
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/11/2020 7:26 AM, Jonathan Marler wrote:
 True.  I estimate around 75% of functions in general don't benefit from named 
 parameters.  So the question becomes, what do we do about parameter name 
 inconsistency in these cases for the standard libraries?  If we don't think 
 named parameters are useful for a function, will we leave them be?   If so,
can 
 we come up with a criteria we can use to determine when named parameters make 
 sense?  I think this would help greatly in this transition to named
parameters 
 to help avoid alot of the bikeshedding I see coming when this is enabled.
Make some PRs to improve the consistency in advance, by all means.
 For example, for math functions like the ones I mentioned, are we going to 
 normalize on "x", "y" and "z" depending on the type?
Sounds reasonable to me. But keep in mind that this will also result in inconsistencies. For example, points will be (x,y,z) triplets.
 And if it's a template that 
 could accept any type, what name would we use in that case?
The most generous of the specializations.
 question still stands for functions that do make sense, do you think we should 
 come up with a standard set of names to promote consistency accross the
standard 
 libraries, and 3rd party libraries?
I find standard names for things, like `p` for generic pointer, and `s` for generic string, and `i` for generic integer, to be valuable. But blind adherence to such will cause trouble, because it's not practical to be entirely consistent.
 Will we try to fix these names before integrating support for named parameters?
I wouldn't go crazy over this, but it would be nice to do it. Also, having good names for parameters is a good idea anyway.
 If we need to change names later, what will the policy be for druntime/phobos 
 for making parameter name changes when inconsistencies are discovered?
Initially, we shouldn't worry about fixing it because few will be using N.P. But later, no, we shouldn't be changing them.
 It looks like the parameter names have been stripped out for the windows 
 functions.  Do you think we should add parameter names in those functions? 
If 
 we do want to add names, do you think we should we use the hungarian notation 
 parameter names from windows, or no?
Should use the names from the official Windows documentation. Ditto for all other APIs. Also, there's no rush to add parameter names to APIs that don't currently have them.
Feb 11
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
 On 2/10/2020 1:02 PM, Manu wrote:
 Named arguments breaks this very important pattern:
Named arguments will not match to ... parameters, so it won't break existing code, it just won't compile if you write new code that tries that.
Just wanted to point out without muddying the feedback thread, that this response completely misses the point. The point is to have a wrapper for origFun which behaves exactly as the original function, but does something special inside. Saying you won't be able to call wrapper with named parameters is the actual point of the post. It would be good to have a response to the fact that it breaks the intention of perfect forwarding. An example: foo(a: 1, b:2); Now I want to replace all calls to foo with a special wrapper that logs all calls. alias foo = logCalls!(.foo); foo(a: 1, b:2); // error, cannot use named parameters with tuples. Is there a plan to mitigate this limitation? -Steve
Feb 11
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 11 February 2020 at 13:52:35 UTC, Steven 
Schveighoffer wrote:
 Is there a plan to mitigate this limitation?
I wrote about this in github comments when the dip pr was first opened: https://github.com/dlang/DIPs/pull/168#discussion_r324481363 lol actually you were the person to push back hardest! __traits(identifier) on the template param is a solid possibility, and the other push back is maybe making it opt-in... but with your __traits(identifier) add on.... no need for my weird struct thingy. So basically the template variadic params would then work identically to the __parameters result we already have (probably including the slice technique lol). There's precedent! That should absolutely work. And could be done right now to solve this in full - with the names being part of the variadic tuple it would forward to calls as well. I like it a lot. But I still think this DIP as-is is an OK addition without it. We can always remove the T... limitation later as well. though wow id really like to have it work.
Feb 11
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/11/20 9:07 AM, Adam D. Ruppe wrote:
 On Tuesday, 11 February 2020 at 13:52:35 UTC, Steven Schveighoffer wrote:
 Is there a plan to mitigate this limitation?
I wrote about this in github comments when the dip pr was first opened: https://github.com/dlang/DIPs/pull/168#discussion_r324481363 lol actually you were the person to push back hardest!
ha, I just pushed back on the idea of a custom struct coming in and the template having to deal with that in a special way ;) But my thoughts have evolved on the importance of this. I think it makes the DIP not worth it if we can't capture those calls properly. Note also: if the template parameters names are part of the tuple type, and therefore part of the template instantiation, we have an actual path to deprecations as well: Date makeDate(int year, int month, int day) {...} deprecated("Use better names please") auto makeDate(T...)(T args) if (containsArgName!("a", T) || containsArgName!("b", T) || containsArgName!("c", T)) { auto makeDateImpl(int a, int b, int c) { // remove names return .makeDate(a, b, c); } return makeDateImpl(args); }
 __traits(identifier) on the template param is a solid possibility, and 
 the other push back is maybe making it opt-in... but with your 
 __traits(identifier) add on.... no need for my weird struct thingy.
 
 So basically the template variadic params would then work identically to 
 the __parameters result we already have (probably including the slice 
 technique lol). There's precedent!
 
 That should absolutely work. And could be done right now to solve this 
 in full - with the names being part of the variadic tuple it would 
 forward to calls as well. I like it a lot.
 
 But I still think this DIP as-is is an OK addition without it. We can 
 always remove the T... limitation later as well.
I think while it doesn't break currently existing code, it breaks the *intention* of code. Something that intends to be a perfect forward of an API can no longer EVER claim that. Manu is right, a whole lot of code out there exists solely to massage APIs, adding one nuance here or there. -Steve
Feb 11
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/11/2020 5:52 AM, Steven Schveighoffer wrote:
 An example:
 
 foo(a: 1, b:2);
 
 Now I want to replace all calls to foo with a special wrapper that logs all
calls.
 
 alias foo = logCalls!(.foo);
 
 foo(a: 1, b:2); // error, cannot use named parameters with tuples.
 
 Is there a plan to mitigate this limitation?
Currently, no. The current plan is named arguments will not match to ... This leaves the door open to a future enhancement along those lines, which is better than trying to gin up an awkward solution.
Feb 11
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/11/20 2:07 PM, Walter Bright wrote:
 On 2/11/2020 5:52 AM, Steven Schveighoffer wrote:
 An example:

 foo(a: 1, b:2);

 Now I want to replace all calls to foo with a special wrapper that 
 logs all calls.

 alias foo = logCalls!(.foo);

 foo(a: 1, b:2); // error, cannot use named parameters with tuples.

 Is there a plan to mitigate this limitation?
Currently, no. The current plan is named arguments will not match to ... This leaves the door open to a future enhancement along those lines, which is better than trying to gin up an awkward solution.
I disagree. If you don't do something about this, the entire realm of wrapping types and functions becomes convoluted and sometimes impossible, because you can't wrap things and have them behave as the original thing as easily as you can today. If we can't figure out a solution, I would say we hold off on named parameters. D's major strength is compile-time introspection and code generation, and this DIP adds a whole new aspect of API that is off-limits to introspection. -Steve
Feb 11
prev sibling parent SashaGreat <s g.com> writes:
On Tuesday, 11 February 2020 at 19:07:23 UTC, Walter Bright wrote:
 On 2/11/2020 5:52 AM, Steven Schveighoffer wrote:
 An example:
 
 foo(a: 1, b:2);
 
 Now I want to replace all calls to foo with a special wrapper 
 that logs all calls.
 
 alias foo = logCalls!(.foo);
 
 foo(a: 1, b:2); // error, cannot use named parameters with 
 tuples.
 
 Is there a plan to mitigate this limitation?
Currently, no. The current plan is named arguments will not match to ... This leaves the door open to a future enhancement along those lines, which is better than trying to gin up an awkward solution.
Sorry but this is another half backed implementation. Sasha.
Feb 12