February 15, 2019
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":
>
> https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md
>
> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete.
>
> 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 by the language maintainers.
>
> Please familiarize yourself with the documentation for the Community Review before participating.
>
> https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review
>
> Thanks in advance to all who participate.

As another alternative, named parameters can be implemented using Tuple/tuple from the Phobos Library. This alternative solution will prevent silent breakage. The caller can not opt-out. This solution adds even more noise to function calls  but typedef can reduce the noise. This solution does not address reordering but can be combined with other solutions that allow for reordering. Here is an example:


import std.typecons;
double get_area(Tuple!(double, "radius") t_radius) {
    double radius = t_radius.radius;
    return 3.14 * radius * radius;
}

double get_area(Tuple!(double, "diameter") t_diameter) {
    double radius = t_diameter.diameter / 2;
    return 3.14 * radius * radius;
}

void main()
{
    import std.stdio;
    auto area = get_area(tuple!"radius"(4.));
    writeln("Area with radius: ", area);
    area = get_area(tuple!"diameter"(8.));
    writeln("Area with diameter: ", area);
}
February 15, 2019
On Friday, 15 February 2019 at 21:05:38 UTC, Golden Rockefeller 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":
>>
>> https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md
>>
>> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete.
>>
>> 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 by the language maintainers.
>>
>> Please familiarize yourself with the documentation for the Community Review before participating.
>>
>> https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review
>>
>> Thanks in advance to all who participate.
>
> As another alternative, named parameters can be implemented using Tuple/tuple from the Phobos Library. This alternative solution will prevent silent breakage. The caller can not opt-out. This solution adds even more noise to function calls  but typedef can reduce the noise. This solution does not address reordering but can be combined with other solutions that allow for reordering. Here is an example:
>
>
> import std.typecons;
> double get_area(Tuple!(double, "radius") t_radius) {
>     double radius = t_radius.radius;
>     return 3.14 * radius * radius;
> }
>
> double get_area(Tuple!(double, "diameter") t_diameter) {
>     double radius = t_diameter.diameter / 2;
>     return 3.14 * radius * radius;
> }
>
> void main()
> {
>     import std.stdio;
>     auto area = get_area(tuple!"radius"(4.));
>     writeln("Area with radius: ", area);
>     area = get_area(tuple!"diameter"(8.));
>     writeln("Area with diameter: ", area);
> }

The downside to your solution is an increases in memory.
February 15, 2019
On Friday, 15 February 2019 at 20:51:35 UTC, 12345swordy wrote:
> On Friday, 15 February 2019 at 20:35:14 UTC, Yuxuan Shui wrote:
>> On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:
>>> [...]
>>
>> I am not saying "we should never break any code". I am deferring that decision to someone else. If someone want to make named parameters opt-out instead of opt-in, they can do so on top of this DIP. I am just not doing that in my proposal.
>
> Why?

You answered the why yourself:

> a.)This is a slow process
> b.)Would require another 180+ days if A&W reject this.

So I don't want this proposal to be rejected.


February 15, 2019
On Friday, 15 February 2019 at 21:19:14 UTC, Yuxuan Shui wrote:
> On Friday, 15 February 2019 at 20:51:35 UTC, 12345swordy wrote:
>> On Friday, 15 February 2019 at 20:35:14 UTC, Yuxuan Shui wrote:
>>> On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:
>>>> [...]
>>>
>>> I am not saying "we should never break any code". I am deferring that decision to someone else. If someone want to make named parameters opt-out instead of opt-in, they can do so on top of this DIP. I am just not doing that in my proposal.
>>
>> Why?
>
> You answered the why yourself:
>
>> a.)This is a slow process
>> b.)Would require another 180+ days if A&W reject this.
>
> So I don't want this proposal to be rejected.

There are severe usability disadvantages that outweigh readability advantages if this were to be opt-in. The decision to used named arguments should rest on the calle not the caller. When the calle used named arguments they are opt-in the risk of their code breakage in which forcing the caller to mark their function @named does NOT solve this.

Here is my statement: The caller is NOT AND SHOULD NOT BE responsible for code breakage when they renamed parameters as the Named Arguments are opt-in from the client side of the code.
Forcing the Caller to be responsible for Named Arguments, is a HUGE usability disadvantage as it requires many existing libraries out there to mark their functions @named if the client wants to use named arguments, when they have already have other attributes to worry about. It even worst for library creators to mark @named in their modules EVERY SINGLE TIME if they to grant the client access to named arguments. Function not having Named Arguments support should be RARE NOT COMMON! This poor design should be the basis of this being rejected.
February 15, 2019
On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:
> ...
> D should not make the fatal mistake of "persevering backwards capability at all cost" scenario, that what c++ is for.
> ...

I agree with this and despite breaking code indeed sucks, for a language like D which has a very small user base, I think it should go for it instead of adding new properties for handling different cases and trying to be like C++.

In fact look for example C++ 17 or 20 and you can clearly see that they are trying hard to force people over new features/ways of programming and hoping the old "habits" go way.

Ron.


February 15, 2019
On Friday, 15 February 2019 at 22:17:28 UTC, Ron J wrote:
> On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:
>> ...
>> D should not make the fatal mistake of "persevering backwards capability at all cost" scenario, that what c++ is for.
>> ...
>
> I agree with this and despite breaking code indeed sucks, for a language like D which has a very small user base, I think it should go for it instead of adding new properties for handling different cases and trying to be like C++.
>
> In fact look for example C++ 17 or 20 and you can clearly see that they are trying hard to force people over new features/ways of programming and hoping the old "habits" go way.
>
> Ron.

The "Old Way" aka C++98 will still be used simply because they still support it. If they are serious about preventing people from coding the "Old Way" then they simply need to stop supporting the "Old Way". Until then the dinosaurs will still type C++98 code.

-Alex
February 15, 2019
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":
>
> https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md
>
> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete.
>
> 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 by the language maintainers.
>
> Please familiarize yourself with the documentation for the Community Review before participating.
>
> https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review
>
> Thanks in advance to all who participate.

drawRect(x: 0, y: 0, width: 1, height: 1);
drawRect(width: 1, height: 1, x: 0, y: 0);

The DIP doesn't state what order these are executed in. The spec states parameters are executed left to right. When you can rearrange the function arguments at the call site, is it going to call left to right as it is orangized at the call site, or left to right as according to as the function definition?

I don't think we should require an attribute for this either. We already have enough we don't need one more.

It means we can't use it for instances where you want to change a default value but keep other options at their default much like how C# implements it:

void foo( int bar, int someDefault = 0, int someOtherDefault = 1 );
foo( 10, someOtherDefault: 2 );
February 16, 2019
On Friday, 15 February 2019 at 17:43:52 UTC, 12345swordy wrote:
> On Friday, 15 February 2019 at 17:38:23 UTC, Francesco Mecca wrote:
>> On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:
>>> [...]
>>
>> I think that the solution proposed by Atila is better for the following reasons:
>> 1. it is a library solution
>> 2. allows both the user and the author of a library to specify functions with named parameters
>> 3. it is very lightweight
>>
>> [...]
>
> You miss the other reason on why it is not enough: Compile time and run-time performance penalty.
> -Alex

I have messed with kwargs and compile time doesn't seem to be an issue. At least it is not noticeable to me and I have a quite old dual core cpu.

What kind of runtime penalty do you incur when using the library?
To me it seems that the only penalty would be error messages.
Also, kwargs allows unordered arguments and that is the path of lowest friction for people coming from languages with named parameters function (python on top of my mind).
It makes sense if you want to improve readibility.

February 16, 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



February 16, 2019
On Saturday, 16 February 2019 at 10:02:02 UTC, Francesco Mecca wrote:
> On Friday, 15 February 2019 at 17:43:52 UTC, 12345swordy wrote:
>> On Friday, 15 February 2019 at 17:38:23 UTC, Francesco Mecca wrote:
>>> On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:
>>>> [...]
>>>
>>> I think that the solution proposed by Atila is better for the following reasons:
>>> 1. it is a library solution
>>> 2. allows both the user and the author of a library to specify functions with named parameters
>>> 3. it is very lightweight
>>>
>>> [...]
>>
>> You miss the other reason on why it is not enough: Compile time and run-time performance penalty.
>> -Alex
>
> I have messed with kwargs and compile time doesn't seem to be an issue. At least it is not noticeable to me and I have a quite old dual core cpu.
>
> What kind of runtime penalty do you incur when using the library?
> To me it seems that the only penalty would be error messages.
> Also, kwargs allows unordered arguments and that is the path of lowest friction for people coming from languages with named parameters function (python on top of my mind).
> It makes sense if you want to improve readibility.

kwargs is not scalable. You can't use the same types as parameters and you have to create a new type for each parameter. It's cumbersome and clunky and it relies on (unenforceable) convention to make the call site more readable. And it doesn't allow the API author to dictate how their function should be called.

Named arguments is not a necessary feature of a language at all, it's only useful for maintenance and readability. There're no technical advantages to the api author, only psychological and aesthetic advantages to the api user, and the many code reviewers and maintainers who will follow them.

Ok there is one technical advantage when it comes to overloads (See a post above). Maybe there're more ... 🤔🤷‍♂️

Cheers,
- Ali