DIP 1019--Named Arguments Lite--Community Review Round 1

aliak something at something.com
Sat Feb 16 11:54:24 UTC 2019


On Friday, 15 February 2019 at 18:26:34 UTC, Yuxuan Shui wrote:
> On Friday, 15 February 2019 at 17:03:40 UTC, aliak wrote:
>> On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:
>>> This is the feedback thread for the first round of Community 
>>> Review for DIP 1019, "Named Arguments Lite":
>>
>> Wee! Named arguments :D
>>
>> There's also another solution that was brought up by Simen.
>>
>> Forum post: 
>> https://forum.dlang.org/post/ejnsqqebrjbwefjhagvg@forum.dlang.org
>> An implementation: 
>> https://github.com/aliak00/ddash/commit/911e3b580e7bbe06f43c258a2d1c78f97a9668c5#diff-6919882fdb1af168f0e5b90603414fae
>>
>> Basically we have the following decision dimensions when 
>> allowing named parameters in APIs
>>
>> Also I'm on the side of named parameters being the default and 
>> the API author deciding if their use is opt-out. But, that's a 
>> compile time breaking change to, basically, everything. So I 
>> guess that's out the window. So, there's probably a better 
>> chance with named parameters being opt-in.
>
> Yes, one of my "design goal" is to maximize my chance :)

Yeah, I understand that. Though, just for the record if it came 
down to a vote, I'd 100% vote for a deprecation path towards 
named-parameters-by-default.

>
>>
>> 1) I don't think it should be re-orderable because it allows 
>> callers to abuse APIs and not be used how the author (may 
>> have) intended:
>>
>> void call(int me, int maybe) {}
>>
>> call(maybe: 3, me: 2);
>> call(me: 2, maybe: 3);
>>
>> Carly Ray would roll in her grave :p Also, who's calling who?!?
>
> I was reluctant about add reordering too. The first version of 
> the proposal doesn't have reordering. But after some thought, I 
> realized reordering cannot be add as an extension of this 
> proposal without breakage. So in order to not rule reordering 
> out, I have to include that in the proposal.
>
> But now I reconsider it again, it is probably not as bad as I 
> thought. The future reordering proposal can probably *also* be 
> opt-in behind a attribute. So I am not really decided at this 
> moment.

Yeah, it may also make it simpler? As in, without reordering the 
resolution order of parameters don't have to be changed. But 
with, then you need to account for that too maybe.

Also one more advantage, the call-site is consistent at every 
usage. Allowing reordering encourages sloppiness on the caller, 
with no particular (at least that I can see) benefit.

>
>>
>> Also, it makes named overload resolution impossible should the 
>> need arise:
>>
>> void call(int a, int b) {}
>> void call(int b, int a) {}
>>
>> call(a: 3, b: 4); // ??
>
> This is a compile time error since the call matches both 
> functions.

But this can be resolved if there was no reordering and "call" 
was a function that "required" named arguments. Or did I miss 
something?

>
>>
>> 2) Then there's the issue of external names and internal 
>> names, as an API designer, I want to be able to specify an 
>> external name but also have a different internal identifier
>>
>> move(T)(T from, T to);
>>
>> Requires the awkward use of variables from and to in the 
>> function body. It's not the end of the world of course, but 
>> allowing external and internal variable naming gives allows 
>> for the best user experience, and code readability from both 
>> caller and API author:
>>
>> move(T)(T from source, T to dest) {
>>   // implementation use source and dest
>> }
>>
>> // caller uses from and to:
>> move(from: x, to: y);
>
> This can be done with this proposal, you do
>
>     move(T)(T source, T dest) { /* code */ }
>     @named move(T)(T from, T to);

Ah, ok, I did not catch that was possible. Cool, that could work 
as well. Requires more typing and maintenance of function 
signatures perhaps, which may be harder to deal with then just 
allowing that kind of functionality in one function signature.


> This proposal doesn't prevent your suggestion from being 
> implemented in the future :)

True, but if we force named parameters across the whole function 
now with something like @named, then what will add a second way 
to have named parameters whereas it can potentially just be 
tackled in one go now. So maybe better to just allow that now? 
Also ":" is  symmetrical with the way you call a named argument 
as well. Thought it would just be a bit nicer than taking up a 
new attribute, which is also quite generically "named".


>
>>
>> [snip]

One thing that could be mentioned in the DIP is the ability to 
allow for function overloads that were previously impossible: 
Consider:

// Function to load a value from a program option
auto createProgramOption(T)(string name, string envVar = null, T 
defaultValue = T.init);

I want to force "name" but optionally have a defaultValue and an 
envVar. What happens if T is a string? How do you make the 
call-site nice?

createProgramOption!int("port", "PORT", 8080); // ok
createProgramOption!string("host", "HOST", "localhost"); // ok

// Now I want to allow these two:
createProgramOption!string("host","localhost"); // defaultValue 
version
createProgramOption!string("host","HOST"); // envVar version

What do I do? How do I achieve this without named arguments?

With named arguments:

auto createProgramOption(T)(string name, string envVar = null, T 
defaultValue = T.init);

createProgramOption!string(name: "host", defaultValue: 
"localhost");
createProgramOption!string(name: "host", envVar: "HOST");

// Just works, intuitive, obvious, readable





More information about the Digitalmars-d mailing list