May 14, 2020
On Thursday, 14 May 2020 at 12:03:13 UTC, Petar Kirov [ZombineDev] wrote:
> [snip]
>
> [1]:
> /sandbox/main.d(5): Error: `library.copy` called with argument types `(string, string)` matches both:
> /sandbox/library.d(1):     `library.copy(string source, string destination)`
> and:
> /sandbox/library.d(7):     `library.copy(string source, string distinasion)`

Interesting that it only mentions two of them and not all of them. If you comment one of them out, then it mentions the other.

To your suggestion above, it's unclear if you are suggesting that the compiler read the deprecation message and change behavior somehow based on it. There is nothing stopping you from providing detailed deprecation messages today. Expanding on Seb's example, you could have something like below.

void foo(int x, int y) { ... }

deprecated("Parameters renamed: `xVal` -> `x` | `yVal` -> `y`")
extern(D, argNames)
void foo(int xVal, int yVal) { ... }

The extern(D, argNames) is from Seb and is what would tell the compiler to only allow calling foo with keyword arguments.

Thinking on it, you could make this even more general and have
extern(D, positionOnly)
extern(D, keywordOnly)
which would force either positionOnly or keywordOnly syntax. That would resolve any concerns that I have.
May 14, 2020
On 5/14/20 9:20 AM, jmh530 wrote:
> On Thursday, 14 May 2020 at 12:03:13 UTC, Petar Kirov [ZombineDev] wrote:
>> [snip]
>>
>> [1]:
>> /sandbox/main.d(5): Error: `library.copy` called with argument types `(string, string)` matches both:
>> /sandbox/library.d(1):     `library.copy(string source, string destination)`
>> and:
>> /sandbox/library.d(7):     `library.copy(string source, string distinasion)`
> 
> Interesting that it only mentions two of them and not all of them. If you comment one of them out, then it mentions the other.
> 
> To your suggestion above, it's unclear if you are suggesting that the compiler read the deprecation message and change behavior somehow based on it. There is nothing stopping you from providing detailed deprecation messages today. Expanding on Seb's example, you could have something like below.
> 
> void foo(int x, int y) { ... }
> 
> deprecated("Parameters renamed: `xVal` -> `x` | `yVal` -> `y`")
> extern(D, argNames)
> void foo(int xVal, int yVal) { ... }
> 
> The extern(D, argNames) is from Seb and is what would tell the compiler to only allow calling foo with keyword arguments.
> 
> Thinking on it, you could make this even more general and have
> extern(D, positionOnly)
> extern(D, keywordOnly)
> which would force either positionOnly or keywordOnly syntax. That would resolve any concerns that I have.

I don't think the extern(D, argNames) idea works. Both foos are mangled exactly the same, so you would have identical symbols in the object file.

However, one COULD provide a prototype simply for renaming parameters (without implementation). I don't think you even need a specialized extern(D, argNames) marking, if the compiler will just prefer non-deprecated matches over deprecated ones.

-Steve
May 14, 2020
On Thursday, 14 May 2020 at 13:33:30 UTC, Steven Schveighoffer wrote:
> On 5/14/20 9:20 AM, jmh530 wrote:
>> On Thursday, 14 May 2020 at 12:03:13 UTC, Petar Kirov [ZombineDev] wrote:
>>> [snip]
>>>
>>> [1]:
>>> /sandbox/main.d(5): Error: `library.copy` called with argument types `(string, string)` matches both:
>>> /sandbox/library.d(1):     `library.copy(string source, string destination)`
>>> and:
>>> /sandbox/library.d(7):     `library.copy(string source, string distinasion)`
>> 
>> Interesting that it only mentions two of them and not all of them. If you comment one of them out, then it mentions the other.
>> 
>> To your suggestion above, it's unclear if you are suggesting that the compiler read the deprecation message and change behavior somehow based on it. There is nothing stopping you from providing detailed deprecation messages today. Expanding on Seb's example, you could have something like below.
>> 
>> void foo(int x, int y) { ... }
>> 
>> deprecated("Parameters renamed: `xVal` -> `x` | `yVal` -> `y`")
>> extern(D, argNames)
>> void foo(int xVal, int yVal) { ... }
>> 
>> The extern(D, argNames) is from Seb and is what would tell the compiler to only allow calling foo with keyword arguments.
>> 
>> Thinking on it, you could make this even more general and have
>> extern(D, positionOnly)
>> extern(D, keywordOnly)
>> which would force either positionOnly or keywordOnly syntax. That would resolve any concerns that I have.
>
> I don't think the extern(D, argNames) idea works. Both foos are mangled exactly the same, so you would have identical symbols in the object file.

The entire point of extern(D, argNames) is that the argument names are now included in the mangling.

It would be analogous to how the other extern declaration affect mangling (e.g. extern(C) will remove all arguments + types).

> However, one COULD provide a prototype simply for renaming parameters (without implementation). I don't think you even need a specialized extern(D, argNames) marking, if the compiler will just prefer non-deprecated matches over deprecated ones.

Yeah, I that would work.
Though the advantage of being able to write a custom body is that now you have a lot more freedom in case the new method differs from the old one by more than argument changes (e.g. semantic or ordering changes):

---
add(int x_s, int y_s) { ... }
@deprecated extern(D, "argNames") add(int x_ms, int y_ms) { add(x_ms * 1000, y_ms * 1000); }
---

Also note that if this would be allowed in the general case the following could work:

---
extern(D, argNames):
int sleep(int msecs) { ... }
int sleep(int secs) { sleep(secs*1000); }
sleep(msecs: 200); // OK
sleep(secs: 100); // OK
sleep(1); // ERROR
---

---
extern(D, argNames):
double sin(double rad) { ... }
double sin(double deg) {  }
sin(rad: 0.5); // OK
sin(deg: 90); // OK
sin(0); // ERROR
---

The compiler would need to trigger an ambiguity error if called without named arguments.
Anyhow, I'm not interested in this general case.

I just think that it could be a way to make deprecation work nicely.

May 14, 2020
On 5/14/20 12:18 PM, Seb wrote:
> On Thursday, 14 May 2020 at 13:33:30 UTC, Steven Schveighoffer wrote:
>> However, one COULD provide a prototype simply for renaming parameters (without implementation). I don't think you even need a specialized extern(D, argNames) marking, if the compiler will just prefer non-deprecated matches over deprecated ones.
> 
> Yeah, I that would work.
> Though the advantage of being able to write a custom body is that now you have a lot more freedom in case the new method differs from the old one by more than argument changes (e.g. semantic or ordering changes):
> 
> ---
> add(int x_s, int y_s) { ... }
> @deprecated extern(D, "argNames") add(int x_ms, int y_ms) { add(x_ms * 1000, y_ms * 1000); }
> ---

I don't think this works, because the parameter names are optional.

In other words, add(1, 2) is going to silently do something else, which defeats the purpose of the deprecation.

A deprecation of semantic meaning or position needs to be handled via a different function name (like it is today).

Which means a deprecated prototype is all that is needed in the case of changing parameter names.

-Steve
May 14, 2020
On Thursday, 14 May 2020 at 16:59:38 UTC, Steven Schveighoffer wrote:
> On 5/14/20 12:18 PM, Seb wrote:
>> On Thursday, 14 May 2020 at 13:33:30 UTC, Steven Schveighoffer wrote:
>>> [...]
>> 
>> Yeah, I that would work.
>> Though the advantage of being able to write a custom body is that now you have a lot more freedom in case the new method differs from the old one by more than argument changes (e.g. semantic or ordering changes):
>> 
>> ---
>> add(int x_s, int y_s) { ... }
>> @deprecated extern(D, "argNames") add(int x_ms, int y_ms) { add(x_ms * 1000, y_ms * 1000); }
>> ---
>
> I don't think this works, because the parameter names are optional.
> In other words, add(1, 2) is going to silently do something else, which defeats the purpose of the deprecation.

Fair point.
I guess this is another argument for providing library author with a mechanism to enforce "by argument name" only.

> A deprecation of semantic meaning or position needs to be handled via a different function name (like it is today).
>
> Which means a deprecated prototype is all that is needed in the case of changing parameter names.

Well, my point was that argument names have the potential for a lot more flexibility.
Anyhow, I'm fine with a deprecated prototype/header as it would already be a lot better than the current status of this DIP (i.e. no options for deprecation).

May 14, 2020
On Thursday, 14 May 2020 at 05:57:15 UTC, Walter Bright wrote:
> Besides, if you really don't want your users to use the parameter names,
>
>     int foo(int _dkfjjiufheuehgthu, long _yer_mother_was_a_hamster, double _I_did_not_read_the_documentation);
>
> and I bet they'll get the message.

I can't tell if this is a joke or not.

If that is your solution instead of adding a feature to disable named parameters on particular functions. Then please incorporate it into the DIP under "best practices" :).


May 14, 2020
On Thursday, 14 May 2020 at 18:59:03 UTC, Arvine wrote:
> On Thursday, 14 May 2020 at 05:57:15 UTC, Walter Bright wrote:
>> Besides, if you really don't want your users to use the parameter names,
>>
>>     int foo(int _dkfjjiufheuehgthu, long _yer_mother_was_a_hamster, double _I_did_not_read_the_documentation);
>>
>> and I bet they'll get the message.
>
> I can't tell if this is a joke or not.
>
> If that is your solution instead of adding a feature to disable named parameters on particular functions. Then please incorporate it into the DIP under "best practices" :).

Personally and with regard to my experience with python I don't think we need a way to disable named parameters. However forcing specific parameters to be used by name, is something I find useful.

If we really cannot live without an opt-out, please use a prefix like '_' (which has a lot of precedence to mean private) and not a function parameter attribute.
May 14, 2020
On 5/12/20 2:22 AM, Jonathan Marler wrote:
> 
> I'd really like to see the DIP include a proposal on parameter naming conventions for the standard libraries before we enable this.
> 

[snip]

> 3. ...

Another convention could be -- if a parameter starts with underscore, then the expectation is that you don't use named parameters with that argument. Such parameter names should always come first, and are subject to the parameter name changing without considering it to break code.

If you use _xyz as a named parameter, and the name changes to _abc, that's your fault.

Just an idea, in the event that we cannot find a good way to have the compiler prevent named parameter usage.

-Steve
May 14, 2020
On Tuesday, 12 May 2020 at 18:57:25 UTC, jmh530 wrote:
> On Monday, 11 May 2020 at 11:37:07 UTC, Mike Parker wrote:
>> [snip]
>
> I think the comments in the prior discussion with respect to Python's positional-only and keyword-only arguments make sense (see [1] for the PEP on this). In particular, the only change I would make to this DIP would be to make it so that keyword arguments are opt-in, such asmaking the syntax something like
> auto functionName(positional_only_parameters, /, positional_or_keyword_parameters) {}
> [snip]

Given the recent discussions, I am reconsidering what I said above.

First, Seb's extern(D, argNames) (or other bikeshedded name) seems worth including. It would mean that keyword_only_parameters could potentially be emulated for people who need that. extern(D, argNames) wouldn't apply to positional_only_parameters.

However, I have reconsidered keeping positional-only as the default. Instead, I would have what this DIP suggests as the default, as in
auto functionName(positional_or_keyword_parameters) {}
However, I would also allow an opt-in for positional only parameters, so that the full syntax would be
auto functionName(positional_only_parameters, /, positional_or_keyword_parameters) {}

Recall Paul's argument (that Walter approved of) that there should be only one set of rules and we already have the struct initialization rules. From the perspective of these edits, the struct initialization rules would be the special case of these for wen there are no positional_only_parameters. Only one set of rules is needed, but you add the ability to handle deprecations and allow positional_only_parameters without resorting to hacks or long, ugly names.
May 14, 2020
On Thursday, 14 May 2020 at 19:55:02 UTC, Steven Schveighoffer wrote:
> Another convention could be -- if a parameter starts with underscore, then the expectation is that you don't use named parameters with that argument. Such parameter names should always come first, and are subject to the parameter name changing without considering it to break code.
>
> If you use _xyz as a named parameter, and the name changes to _abc, that's your fault.

+1

For those who want automatic enforcement, maybe a check for this could be added to D-Scanner?