Jump to page: 1 212  
Page
Thread overview
DIP 1019--Named Arguments Lite--Community Review Round 2
Jun 05
Exil
Jun 06
Exil
Jun 06
Exil
Jun 06
Exil
Jun 05
Kagamin
Jun 08
Kagamin
Jun 06
Exil
Jun 06
Exil
Jun 07
Exil
Jun 06
Aliak
Jun 07
aliak
Jun 07
aliak
Jun 08
Kagamin
Jun 09
aliak
Jun 09
aliak
Jun 09
aliak
Jun 09
aliak
Jun 09
aliak
Jun 09
aliak
Jun 09
Aliak
June 05
This is the feedback thread for the second round of Community Review for DIP 1019, "Named Arguments Lite":

https://github.com/dlang/DIPs/blob/9c9cc39246de4c449fe1e6cb6b27f7e426ff1eb9/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 June 19, or when I make a post declaring it complete.

At the end of Round 2, 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.

I have recently made minor revisions to the DIP process and implemented guidelines for reviewers. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines:

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

I also recommend that everyone read my recent blog post on the topic:

https://dlang.org/blog/2019/06/04/revisions-to-the-dip-process/

To be clear, I will be moving (copying, deleting, and pasting in a new thread) posts that do not adhere to the reviewer guidelines. Please direct any comments on the new documentation to a new thread or to personal email. Please, let's keep the review discussion on topic.

Thanks in advance to all who participate.
June 05
On Wednesday, 5 June 2019 at 13:03:26 UTC, Mike Parker wrote:
> This is the feedback thread for the second round of Community Review for DIP 1019, "Named Arguments Lite":
>
> [...]

Thanks, I wanted this:

```D

void fun(int a = 0, string b = "B", short c = 8080, string d = "D");

void main()
{
    fun(a: 1, d: "ddd");
    fun(b: "bbb", d: "ddd");
}
```
June 05
> Named arguments proposed by this DIP have no effect on the ordering of arguments in function calls.

I feel like this needs to be expanded. Does it mean that using named parameters the parameters still need to follow the same order?

> Named arguments proposed by this DIP do not allow default parameters to be skipped..

Please expand this sentence. Why isn't this being proposed/implemented? This is extremely useful.

    void fun(int a = 0, int lot = 1, int of = 2, int parameters = 4, int foo = 5);

    fun( foo: 10 );
    fun( 0, 1, 2, 4, foo: 10 ); // need to repeat parameters needlessly

> If a function is defined with some of its parameter names omitted, arguments to those parameters can labeled with an empty name.
>
> void fun(int);
>
> fun(:10);

Why is this included, what is the use case for it? Why wouldn't you just use fun(10) instead? If ordering is required why require the ":" at all?

I also don't see anywhere that this wouldn't be allowed?

   void fun( int a, int b );
   fun( a: 0, 10 );

The description shows this:

    void drawRect(int x, int y, int width, int height);

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

But there is nothing in the DIP that states that this is valid or what rules it needs to follow? Like above with the named parameter appearing before arguments or inbetween.


> Overridden member functions can be called with a set of names matching any of the function definitions which are visible through the object used to call those functions.
>
> class A {
>     int a(int x);
> }
> 
> class B : A {
>     override int a(int z);
> }
> 
> auto b = new B;
> A a = cast(A)b;
> 
> b.a(z: 1); // valid
> b.a(x: 1); // valid
> a.a(x: 1); // valid
> a.a(z: 1); // error

Which functions do these call? Does b.a(x: 1) call B.a() or A.a()? You can call A.a() specifically, this needs to be clarified as to which is called.


https://run.dlang.io/is/eQ7X4p

import std.stdio;

class A {
    void a(int x) { writeln("A"); }
 }
class B : A {
    override void a(int z) { writeln("B"); }
}

void main() {
 	auto b = new B;

    b.A.a( 10 );
    b.a( 10 );
}


June 05
Remove the variadic functions section. That's a tuple parameter, not variadic, and should use (future) tuple syntax.
June 05
On Wednesday, 5 June 2019 at 15:25:52 UTC, Exil wrote:
> I also don't see anywhere that this wouldn't be allowed?
>
>    void fun( int a, int b );
>    fun( a: 0, 10 );
>

Yes.

> The description shows this:
>
>     void drawRect(int x, int y, int width, int height);
>
>     drawRect(x: 0, y: 0, width: 1, height: 1);
>     drawRect(0, 0, width: 1, height: 1); // Also valid
>
> But there is nothing in the DIP that states that this is valid or what rules it needs to follow? Like above with the named parameter appearing before arguments or inbetween.
>

Named arguments in this proposal are not positional parameters, they're more annotations. The ordinary order of parameters needs to be respected. (That's what makes it "Lite".) That's also why you can't skip default parameters.

> https://run.dlang.io/is/eQ7X4p
>
> import std.stdio;
>
> class A {
>     void a(int x) { writeln("A"); }
>  }
> class B : A {
>     override void a(int z) { writeln("B"); }
> }
>
> void main() {
>  	auto b = new B;
>
>     b.A.a( 10 );
>     b.a( 10 );
> }

This "feature" is nonsense and should be removed. It goes against the entire point of function overriding. It's also not in the spec.

What is in the spec is the ability to do this with fields, ie. "int a" in B hiding "int a" in A, and I suspect this is a side effect of that feature. (Which makes sense, for fields, as field hiding is fundamentally different from method overriding.) Strictly speaking the spec says "members of a base class", but I strongly hope the use for methods is unintentional.
June 05
On Wednesday, 5 June 2019 at 13:03:26 UTC, Mike Parker wrote:
> This is the feedback thread for the second round of Community Review for DIP 1019, "Named Arguments Lite":
>
> https://github.com/dlang/DIPs/blob/9c9cc39246de4c449fe1e6cb6b27f7e426ff1eb9/DIPs/DIP1019.md

Quoting the DIP:

> Future changes
> 
> This DIP does not prohibit future proposals for adding parameter reordering, partially-specified parameter names with reordering, named template parameters, omission of default arguments by using named arguments, and other similar things. Nor does it prohibit the inclusion of parameter names as part of mangled function names.

I'd argue this claim is false.

Forward declarations don't work together with those things nicely:
```
int f(int a, int b);
int f(int b, int a) {...}
void main() {
    f(a: 1, b: 2); // according to the DIP, this calls f(2, 1)
}
```
What happens if parameter reordering are supported?  If you're consistent with the rest of D, the call needs to be changed to f(1, 2).  Which is a silent breakage!
That's because in D the definition has somehow more weight than the forward declarations:
```
void f(int a=1);
void f(int a=2);
void f(int a) { ... }

void g(int a=1);
void g(int a=2) { ... }

void main() {
  f(); // Error: f called with argument types () matches both: f(int a = 1) and f(int a = 2)
  g(); // calls g(2)
}
```
The only way I see to sanely introduce reordering would be to treat forward declarations and the definition equally and refuse to compile if there's any ambiguity.  Which is a fairly impactful change that breaks code, even if that code doesn't use named arguments.

So unless someone has a good idea how to deal with those cases, I'd say:

- named arguments without forward declarations are fine (we can add more stuff later without problems)
- named arguments with forward declarations, i.e. the current DIP, blocks a later addition of reordering unless you accept code breakage
- named arguments with forward declarations AND reordering right away are fine too, but require a spec that is a little bit inconsistent with the rest of D.
June 06
On Wednesday, 5 June 2019 at 15:25:52 UTC, Exil wrote:
> [snip]
>> If a function is defined with some of its parameter names omitted, arguments to those parameters can labeled with an empty name.
>>
>> void fun(int);
>>
>> fun(:10);
>
> Why is this included, what is the use case for it? Why wouldn't you just use fun(10) instead? If ordering is required why require the ":" at all?

None of the names are required. This is provided so there is a way to label unnamed parameters if there is a need for it.

>
>> Overridden member functions can be called with a set of names matching any of the function definitions which are visible through the object used to call those functions.
>>
>> class A {
>>     int a(int x);
>> }
>> 
>> class B : A {
>>     override int a(int z);
>> }
>> 
>> auto b = new B;
>> A a = cast(A)b;
>> 
>> b.a(z: 1); // valid
>> b.a(x: 1); // valid
>> a.a(x: 1); // valid
>> a.a(z: 1); // error
>
> Which functions do these call? Does b.a(x: 1) call B.a() or A.a()? You can call A.a() specifically, this needs to be clarified as to which is called.

Parameter names have no effect on which function get called (as stressed by this DIP). I will clarify that more in the next revision.


June 06
On Wednesday, 5 June 2019 at 23:00:29 UTC, Guillaume Boucher wrote:
> On Wednesday, 5 June 2019 at 13:03:26 UTC, Mike Parker wrote:
>> This is the feedback thread for the second round of Community Review for DIP 1019, "Named Arguments Lite":
>>
>> https://github.com/dlang/DIPs/blob/9c9cc39246de4c449fe1e6cb6b27f7e426ff1eb9/DIPs/DIP1019.md
>
> Quoting the DIP:
>
>> Future changes
>> 
>> This DIP does not prohibit future proposals for adding parameter reordering, partially-specified parameter names with reordering, named template parameters, omission of default arguments by using named arguments, and other similar things. Nor does it prohibit the inclusion of parameter names as part of mangled function names.
>
> I'd argue this claim is false.
>
> [snip]
>
> The only way I see to sanely introduce reordering would be to treat forward declarations and the definition equally and refuse to compile if there's any ambiguity.  Which is a fairly impactful change that breaks code, even if that code doesn't use named arguments.

This won't break other code if this is only applied to call sites that use named arguments.

>
> So unless someone has a good idea how to deal with those cases, I'd say:
>

June 06
On Wednesday, 5 June 2019 at 21:24:35 UTC, FeepingCreature wrote:
> On Wednesday, 5 June 2019 at 15:25:52 UTC, Exil wrote:
>> I also don't see anywhere that this wouldn't be allowed?
>>
>>    void fun( int a, int b );
>>    fun( a: 0, 10 );
>>
>
> Yes.

That wasn't a yes or no question...

>> The description shows this:
>>
>>     void drawRect(int x, int y, int width, int height);
>>
>>     drawRect(x: 0, y: 0, width: 1, height: 1);
>>     drawRect(0, 0, width: 1, height: 1); // Also valid
>>
>> But there is nothing in the DIP that states that this is valid or what rules it needs to follow? Like above with the named parameter appearing before arguments or inbetween.
>>
>
> Named arguments in this proposal are not positional parameters, they're more annotations. The ordinary order of parameters needs to be respected. (That's what makes it "Lite".) That's also why you can't skip default parameters.

It should still specify the rules for which it has to follow, which it doesn't currently.

The DIP states that it doesn't prevent a future DIP from allowing reordering and default parameters. But if this DIP is implemented it will become extremely difficult to implement such a feature in the future. It needs to go into detail why this feature isn't being included. I feel like because this is "Lite" is not a sufficient answer. You only get one chance to implement a feature like this, once it is in, there is not going to be changing it. If something is going to be excluded it should have a valid reason behind why it is not included.

>> https://run.dlang.io/is/eQ7X4p
>>
>> import std.stdio;
>>
>> class A {
>>     void a(int x) { writeln("A"); }
>>  }
>> class B : A {
>>     override void a(int z) { writeln("B"); }
>> }
>>
>> void main() {
>>  	auto b = new B;
>>
>>     b.A.a( 10 );
>>     b.a( 10 );
>> }
>
> This "feature" is nonsense and should be removed. It goes against the entire point of function overriding. It's also not in the spec.
>
> What is in the spec is the ability to do this with fields, ie. "int a" in B hiding "int a" in A, and I suspect this is a side effect of that feature. (Which makes sense, for fields, as field hiding is fundamentally different from method overriding.) Strictly speaking the spec says "members of a base class", but I strongly hope the use for methods is unintentional.

Wouldn't make sense if you couldn't access all members of a base class. A method is a member of a class. Also the spec is outdated and incorrect in a lot of aspects.


June 06
On Thursday, 6 June 2019 at 10:05:45 UTC, Yuxuan Shui wrote:
> On Wednesday, 5 June 2019 at 15:25:52 UTC, Exil wrote:
>> [snip]
>>> If a function is defined with some of its parameter names omitted, arguments to those parameters can labeled with an empty name.
>>>
>>> void fun(int);
>>>
>>> fun(:10);
>>
>> Why is this included, what is the use case for it? Why wouldn't you just use fun(10) instead? If ordering is required why require the ":" at all?
>
> None of the names are required. This is provided so there is a way to label unnamed parameters if there is a need for it.

Right, but if you are forcing the order of parameter be kept. How would having an empty parameter name help anyone identify what it is? It is an extra feature that doesn't provide or have any purpose.

foo(:10)

is as informative as

foo(10)

Same thing for the following:

foo(10, 20, :30);
foo(10, 20, 30);

If anything the colon adds to confusion.
« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10 11