February 07, 2020
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).
February 07, 2020
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.
February 07, 2020
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
February 07, 2020
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
February 07, 2020
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.
February 07, 2020
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.

+1. I never used this feature in C# for example.

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.
February 07, 2020
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.
> 
> +1. I never used this feature in C# for example.
> 
> 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
February 07, 2020
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.
February 07, 2020
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.

By the way one interesting and funny thing in C# documentation:

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.
February 07, 2020
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.