www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP 1019--Named Arguments Lite--Community Review Round 2

reply Mike Parker <aldacron gmail.com> writes:
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.
Jun 05
next sibling parent zoujiaqing <zoujiaqing gmail.com> writes:
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"); } ```
Jun 05
prev sibling next sibling parent reply Exil <Exil gmall.com> writes:
 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 ); }
Jun 05
next sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
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.
Jun 05
parent reply Exil <Exil gmall.com> writes:
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.
Jun 06
parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Thursday, 6 June 2019 at 13:13:45 UTC, Exil wrote:
 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...
Yes, this would be allowed in the spec as it stands.
 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.
Since it's a virtual method, accessing it as a base class member shouldn't do anything, because it should result in the same vtable slot. You don't just access it as a base class member, you access it *as a static method reference*. This is nonsense.
 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.
If you think this proposal would block later work on named arguments, this is probably a strong reason against it. My impression is that this is very much intended as a "foot in the door" for named arguments, to demonstrate that the sky will not fall if they are implemented. I agree that as a "named parameters for now and forevermore" it is disappointingly sparse. The lack of ability to skip default parameters seems particularly crippling. Personally, varying the order of parameters doesn't matter to me, so if that's the cost of getting named parameters I'd pay it happily. But I think the problem in general is that we have a variety of proposals, and people have argued for, or especially against, parts of those proposals almost independently. I don't think it's accurate to say that there's "camps" of proposals; rather, almost every part of named arguments seems to have people who strenuously disagree and think it'll make the language worse - but there's no obvious consensus or commonality. This naturally makes it hard to craft a compromise. I believe that Named Arguments Lite is an attempt to guess which set of compromises will put off the least people while being acceptable to the most and delivering at least some value to everybody who wants at least some part of named arguments. For me, the lack of ability to skip default arguments is a dealbreaker, particularly if accepting this proposal would mean that it would be the face of named arguments in D forevermore, but if it was "this or literally nothing else ever" I'd be in favor. So I guess the question rests on whether if this is rejected, there'll be a "D Named Arguments Proper" after. And, uh, looking at "shared", that seems unlikely for at least several years. So to me the question is "this or nothing", and even though it doesn't solve the main usecase I'd want it for (verbose constructors, which *needs* the ability to skip default arguments), it is at least better than the alternative, which is nothing. Though of course any change that would leave the door open for skipping parameters would be welcome.
Jun 06
next sibling parent reply Exil <Exil gmall.com> writes:
On Thursday, 6 June 2019 at 13:47:57 UTC, FeepingCreature wrote:
 On Thursday, 6 June 2019 at 13:13:45 UTC, Exil wrote:
 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...
Yes, this would be allowed in the spec as it stands.
Bit of a nitpick here, I know other people that do the same thing. If you do want to take it as a question, "This wouldn't be allowed?", answering "yes" means that the feature wouldn't be allowed in the spec. It is the inverse of the question "This would be allowed?", you answer "yes" to this question to have the meaning you intended. The question and it's inverse can't have the same meaning for the same answer.
 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.
Since it's a virtual method, accessing it as a base class member shouldn't do anything, because it should result in the same vtable slot. You don't just access it as a base class member, you access it *as a static method reference*. This is nonsense.
It is not nonsense, if you have a chain of 3 class A -> B -> C and in C you need to call A's method over B's overriden. You do so using the same syntax. A.foo(). It would be worse if you have some code that you couldn't access and now you need some kind of a hack just to access it. Anyways this is getting off topic.
 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.
If you think this proposal would block later work on named arguments, this is probably a strong reason against it. My impression is that this is very much intended as a "foot in the door" for named arguments, to demonstrate that the sky will not fall if they are implemented. I agree that as a "named parameters for now and forevermore" it is disappointingly sparse. The lack of ability to skip default parameters seems particularly crippling. Personally, varying the order of parameters doesn't matter to me, so if that's the cost of getting named parameters I'd pay it happily. But I think the problem in general is that we have a variety of proposals, and people have argued for, or especially against, parts of those proposals almost independently. I don't think it's accurate to say that there's "camps" of proposals; rather, almost every part of named arguments seems to have people who strenuously disagree and think it'll make the language worse - but there's no obvious consensus or commonality. This naturally makes it hard to craft a compromise. I believe that Named Arguments Lite is an attempt to guess which set of compromises will put off the least people while being acceptable to the most and delivering at least some value to everybody who wants at least some part of named arguments. For me, the lack of ability to skip default arguments is a dealbreaker, particularly if accepting this proposal would mean that it would be the face of named arguments in D forevermore, but if it was "this or literally nothing else ever" I'd be in favor. So I guess the question rests on whether if this is rejected, there'll be a "D Named Arguments Proper" after. And, uh, looking at "shared", that seems unlikely for at least several years. So to me the question is "this or nothing", and even though it doesn't solve the main usecase I'd want it for (verbose constructors, which *needs* the ability to skip default arguments), it is at least better than the alternative, which is nothing. Though of course any change that would leave the door open for skipping parameters would be welcome.
Was there even anyone arguing against allowing named parameters to be used with default parameters? I've only seen people asking for the feature, like yourself. The people arguing against the feature are those that simply don't want the feature at all because they don't want to have to worry about renaming function parameters. That's the only argument I've seen. I haven't heard one against allow default parameters to be used as they were intended, specifically.
Jun 06
parent FeepingCreature <feepingcreature gmail.com> writes:
On Thursday, 6 June 2019 at 14:18:14 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 13:47:57 UTC, FeepingCreature wrote:
 On Thursday, 6 June 2019 at 13:13:45 UTC, Exil wrote:
 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?
Yes.
That wasn't a yes or no question...
Yes, this would be allowed in the spec as it stands.
Bit of a nitpick here, I know other people that do the same thing. If you do want to take it as a question, "This wouldn't be allowed?", answering "yes" means that the feature wouldn't be allowed in the spec. It is the inverse of the question "This would be allowed?", you answer "yes" to this question to have the meaning you intended. The question and it's inverse can't have the same meaning for the same answer.
Nitpicking right back: what you said was "I don't see anywhere that this wouldn't be allowed". So there's a double negation in play; my "yes" was affirming that you don't see it ... because it isn't there, because it would be allowed.
 It is not nonsense, if you have a chain of 3 class A -> B -> C
 and in C you need to call > A's method over B's overriden.
Right, the problem is that you can have class A -> B -> C, and then you have module D with a void foo(), and in void foo() you have a class of C and you want to call A's method. That currently works, but it shouldn't, because it overrides C's authority to redefine methods from the superclass and makes code very hard to follow, because you can't tell which method was called when foo() was invoked from looking at the type of the object, you have to look at the callsite too. You can end up with code like class A { void foo() { bar(); } void bar() { } } class B : A { void foo() { bar(); } void bar() { } } B b = new B; b.A.foo(); So in B.bar(), you cannot assume you were even called from B.foo()! There's just no reason to permit shenanigans of this degree of inanity.
 Was there even anyone arguing against allowing named parameters 
 to be used with default parameters?
Then I don't see any reason to include in this spec concessions to people who would disagree with the spec regardless. I don't think there's an argument on the merits to not permit skipping default parameters.
Jun 06
prev sibling parent Yuxuan Shui <yshuiv7 gmail.com> writes:
On Thursday, 6 June 2019 at 13:47:57 UTC, FeepingCreature wrote:
 [snip]

 This naturally makes it hard to craft a compromise. I believe 
 that Named Arguments Lite is an attempt to guess which set of 
 compromises will put off the least people while being 
 acceptable to the most and delivering at least some value to 
 everybody who wants at least some part of named arguments.
Thanks for put it so clearly.
 For me, the lack of ability to skip default arguments is a 
 dealbreaker, particularly if accepting this proposal would mean 
 that it would be the face of named arguments in D forevermore, 
 but if it was "this or literally nothing else ever" I'd be in 
 favor. So I guess the question rests on whether if this is 
 rejected, there'll be a "D Named Arguments Proper" after. And, 
 uh, looking at "shared", that seems unlikely for at least 
 several years. So to me the question is "this or nothing", and 
 even though it doesn't solve the main usecase I'd want it for 
 (verbose constructors, which *needs* the ability to skip 
 default arguments), it is at least better than the alternative, 
 which is nothing. Though of course any change that would leave 
 the door open for skipping parameters would be welcome.
I think skipping default arguments will a really simple and straightforward DIP on top of this. Especially given the recent revision of the DIP process. I don't see how lacking that feature could be a dealbreaker.
Jun 07
prev sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
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.
Jun 06
parent Exil <Exil gmall.com> writes:
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.
Jun 06
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
Remove the variadic functions section. That's a tuple parameter, 
not variadic, and should use (future) tuple syntax.
Jun 05
parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Wednesday, 5 June 2019 at 15:41:08 UTC, Kagamin wrote:
 Remove the variadic functions section. That's a tuple 
 parameter, not variadic, and should use (future) tuple syntax.
Are you suggesting we will be forced to call void func(Args...)(int, Args); Like this: func(1, (1,2,3)); In the future?
Jun 07
parent Kagamin <spam here.lot> writes:
On Friday, 7 June 2019 at 13:25:21 UTC, Yuxuan Shui wrote:
 On Wednesday, 5 June 2019 at 15:41:08 UTC, Kagamin wrote:
 Remove the variadic functions section. That's a tuple 
 parameter, not variadic, and should use (future) tuple syntax.
Are you suggesting we will be forced to call void func(Args...)(int, Args); Like this: func(1, (1,2,3)); In the future?
I mean syntax of named arguments, syntax of positional arguments doesn't change.
Jun 08
prev sibling next sibling parent reply Guillaume Boucher <guillaume.boucher.d outlook.com> writes:
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.
Jun 05
parent Yuxuan Shui <yshuiv7 gmail.com> writes:
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:
Jun 06
prev sibling next sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
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

 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.
There's a big issue with this DIP. It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it. I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e. add(int x, int y) // parameter names not helpful square(float x) // parameter names not helpful write(string s) // parameter names not helpful void opEquals(T)(ref T other) // parameter names not helpful Of course there are many cases where named arguments are very helpful (the DIP provides some examples of this). However, if you suddenly allow every caller to specify the argument names to any parameter on any function, you've added a whole new set of dependencies between every function and its callers. A layer of protection/encapsulation has been completely removed. It would be like if we suddenly disabled the "private" modifier and allowed everything to access private fields within structs and classes. Languages like python that uses kwargs don't expose the names of all parameters. They are able to pick and choose which parameters should be named. This allows them to keep that layer of protection/encapsulation for the parameters where the name doesn't matter to the caller, just like when you have private fields where the name doesn't matter to an outside component. D should follow this pattern as it has been successful in other languages and the alternative has too much disadvantage. Allowing a parameter to be named at the call-site should be an "opt-in" feature done at the function definition, so as not to expose the names of all the other parameters that don't make sense to expose to the caller.
Jun 06
next sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler 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

 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.
There's a big issue with this DIP. It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it. I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e. add(int x, int y) // parameter names not helpful square(float x) // parameter names not helpful write(string s) // parameter names not helpful void opEquals(T)(ref T other) // parameter names not helpful Of course there are many cases where named arguments are very helpful (the DIP provides some examples of this). However, if you suddenly allow every caller to specify the argument names to any parameter on any function, you've added a whole new set of dependencies between every function and its callers. A layer of protection/encapsulation has been completely removed. It would be like if we suddenly disabled the "private" modifier and allowed everything to access private fields within structs and classes. Languages like python that uses kwargs don't expose the names of all parameters. They are able to pick and choose which parameters should be named. This allows them to keep that layer of protection/encapsulation for the parameters where the name doesn't matter to the caller, just like when you have private fields where the name doesn't matter to an outside component. D should follow this pattern as it has been successful in other languages and the alternative has too much disadvantage. Allowing a parameter to be named at the call-site should be an "opt-in" feature done at the function definition, so as not to expose the names of all the other parameters that don't make sense to expose to the caller.
By the way, I like what the DIP is trying to do, where it is trying to enable named parameters using the "least common denominator". It attempts to do as little as possible to increase the likelihood of acceptance and leaves room for future improvements to address things like re-ordering/omission of default parameters, features which may or may not be justified but shouldn't keep us from having named parameters. However, the way in which it was designed where it suddenly exposes the parameter names of all functions to all callers is not what we want. I think the "least common denominator" is to provide some way for the function definition to distinguish between named and un-named parameters. Something like this: void foo(int a, int b, int c, alias int d, int e, int f) ^ ^ unnamed parameters (left of alias) named parameters (right of alias) foo(1, 2, 3, d:4, e:5, f:6)
Jun 06
parent Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 19:30:36 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
 [...]
By the way, I like what the DIP is trying to do, where it is trying to enable named parameters using the "least common denominator". It attempts to do as little as possible to increase the likelihood of acceptance and leaves room for future improvements to address things like re-ordering/omission of default parameters, features which may or may not be justified but shouldn't keep us from having named parameters. However, the way in which it was designed where it suddenly exposes the parameter names of all functions to all callers is not what we want. I think the "least common denominator" is to provide some way for the function definition to distinguish between named and un-named parameters. Something like this: void foo(int a, int b, int c, alias int d, int e, int f) ^ ^ unnamed parameters (left of alias) named parameters (right of alias) foo(1, 2, 3, d:4, e:5, f:6)
One more thought, probably should be `public` instead of `alias` to enabled named parameters: void drawRect(public int x, int y, int width, int height); drawRect(x: 0, y: 0, width: 1, height: 1); void calculateProduct(int[] values, public int multipler, public bool goFast, Allocator* allocator); calculateProduct(value, multiplier: 7, goFast: false, allocator: null);
Jun 06
prev sibling next sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
 There's a big issue with this DIP.  It immediately allows any 
 function call to increase coupling with the corresponding 
 function definition with no way to disable it.
I just want to explicitly note that increasing coupling between the call site and the function definition is the entire point of named parameters.
Jun 06
next sibling parent Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 19:50:09 UTC, FeepingCreature wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
 There's a big issue with this DIP.  It immediately allows any 
 function call to increase coupling with the corresponding 
 function definition with no way to disable it.
I just want to explicitly note that increasing coupling between the call site and the function definition is the entire point of named parameters.
Correct. But you don't want to increase everywhere with no way to disable it. Parameters names have been completely private from the caller for the life of D, and you suddenly expose ALL OF THEM. What's worse is unnamed parameters are preferred in the majority of cases, so you're increasing coupling for EVERY case to help the rare cases where it you actually want it.
Jun 06
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, June 6, 2019 1:50:09 PM MDT FeepingCreature via Digitalmars-d 
wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
 There's a big issue with this DIP.  It immediately allows any
 function call to increase coupling with the corresponding
 function definition with no way to disable it.
I just want to explicitly note that increasing coupling between the call site and the function definition is the entire point of named parameters.
Which is precisely why I really hope that no named parameter DIP is ever accepted. It means that suddenly the parameter names are part of the API, meaning that there's yet another point where you have to worry about breaking user code and another point where you have to worry about naming things really well and where people will then bikeshed names. E.G. right now, there is zero attempt in Phobos to name all range parameters the same, and there's no need to, but if named parameters become a thing (especially without requiring that the function be annotated to allow them), then suddenly, we have naming problems all over the place when we didn't before, because the naming isn't consistent. IMHO, named parameters are rarely useful with well-written code. They're primarily of benefit when you have a lot of function parameters, which is bad design. And they're a particularly odd design choice in a language where you're allowed to have interface files that don't even have to provide parameter names let alone make them match the ones in the .d file. But I suppose that there isn't much point in my expressing how much I hate DIPs like this in review threads, since such threads are really just for helping to improve the DIP, not vote it down. The decision on that is solely up to Walter and Andrei (or Atila now, I guess). - Jonathan M Davis
Jun 06
parent Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 21:46:14 UTC, Jonathan M Davis wrote:
 On Thursday, June 6, 2019 1:50:09 PM MDT FeepingCreature via 
 Digitalmars-d wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler 
 wrote:
 There's a big issue with this DIP.  It immediately allows 
 any function call to increase coupling with the 
 corresponding function definition with no way to disable it.
I just want to explicitly note that increasing coupling between the call site and the function definition is the entire point of named parameters.
Which is precisely why I really hope that no named parameter DIP is ever accepted. It means that suddenly the parameter names are part of the API, meaning that there's yet another point where you have to worry about breaking user code and another point where you have to worry about naming things really well and where people will then bikeshed names. E.G. right now, there is zero attempt in Phobos to name all range parameters the same, and there's no need to, but if named parameters become a thing (especially without requiring that the function be annotated to allow them), then suddenly, we have naming problems all over the place when we didn't before, because the naming isn't consistent.
Exactly.
 IMHO, named parameters are rarely useful with well-written 
 code. They're primarily of benefit when you have a lot of 
 function parameters, which is bad design. And they're a 
 particularly odd design choice in a language where you're 
 allowed to have interface files that don't even have to provide 
 parameter names let alone make them match the ones in the .d 
 file.
I mostly agree. Though I estimate they are sometimes useful even with a well-written interface, but, it is more rare. Hence why I think an "opt-in" version would work well. Just add "public" to the parameters you want to expose the names of. Same semantics as fields of classes and structs. Default to private, add "public" if you want the caller to see the name. void foo(T t, public bool log); foo(t, log: true);
 But I suppose that there isn't much point in my expressing how 
 much I hate DIPs like this in review threads, since such 
 threads are really just for helping to improve the DIP, not 
 vote it down. The decision on that is solely up to Walter and 
 Andrei (or Atila now, I guess).
But I'm sure they read these threads when reviewing.
Jun 06
prev sibling next sibling parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler 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

 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.
There's a big issue with this DIP. It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it. I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e. add(int x, int y) // parameter names not helpful square(float x) // parameter names not helpful write(string s) // parameter names not helpful void opEquals(T)(ref T other) // parameter names not helpful Of course there are many cases where named arguments are very helpful (the DIP provides some examples of this). However, if you suddenly allow every caller to specify the argument names to any parameter on any function, you've added a whole new set of dependencies between every function and its callers. A layer of protection/encapsulation has been completely removed. It would be like if we suddenly disabled the "private" modifier and allowed everything to access private fields within structs and classes. Languages like python that uses kwargs don't expose the names of all parameters. They are able to pick and choose which parameters should be named. This allows them to keep that layer of protection/encapsulation for the parameters where the name doesn't matter to the caller, just like when you have private fields where the name doesn't matter to an outside component. D should follow this pattern as it has been successful in other languages and the alternative has too much disadvantage. Allowing a parameter to be named at the call-site should be an "opt-in" feature done at the function definition, so as not to expose the names of all the other parameters that don't make sense to expose to the caller.
This has been brought up in the discussion regarding named arguments for DIP1020 (more specifically the named attribute) and so far I am not convinced that this is an issue that needs to be address, and found it be be overblown given that we have powerful rename tools at this day of age. Having it "opt-in" have it own downsides as the users have to request library developers to add the capability to their libraries. Among many other issues that were brought up and discuss with "opt-in"ing DIP1020. Alex
Jun 06
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 20:04:09 UTC, 12345swordy wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
 [...]
This has been brought up in the discussion regarding named arguments for DIP1020 (more specifically the named attribute) and so far I am not convinced that this is an issue that needs to be address, and found it be be overblown given that we have powerful rename tools at this day of age. Having it "opt-in" have it own downsides as the users have to request library developers to add the capability to their libraries. Among many other issues that were brought up and discuss with "opt-in"ing DIP1020. Alex
Rename tools are irrelevant as they only work when you're in a single project. Exposing the parameters names of every function would mean the we would pretty much need to keep all the parameter names in every function in druntime/phobos, otherwise we would break compatibility. Far to high of a cost just to allow some cases to be more readable. However, if you make it opt-in, then you don't have to pay that cost for EVERY function, you only increase coupling in the cases that make sense.
Jun 06
next sibling parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Thursday, 6 June 2019 at 20:10:06 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 20:04:09 UTC, 12345swordy wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler 
 wrote:
 [...]
This has been brought up in the discussion regarding named arguments for DIP1020 (more specifically the named attribute) and so far I am not convinced that this is an issue that needs to be address, and found it be be overblown given that we have powerful rename tools at this day of age. Having it "opt-in" have it own downsides as the users have to request library developers to add the capability to their libraries. Among many other issues that were brought up and discuss with "opt-in"ing DIP1020. Alex
Rename tools are irrelevant as they only work when you're in a single project.
No, they are not irrelevant, that what C# developers such as myself use when the named argument name has been change.
  Exposing the parameters names of every function would mean the 
 we would pretty much need to keep all the parameter names in 
 every function in druntime/phobos, otherwise we would break 
 compatibility.
We have a deprecated attribute for a very good reason.
 Far to high of a cost just to allow some cases to be more 
 readable.
I strongly reject this claim, due to the lack to evidence. I encounter no apocalypse scenario when it comes to unable to named arguments in the C# community which you can not opt it out. Alex
Jun 06
next sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Thursday, 6 June 2019 at 20:22:17 UTC, 12345swordy wrote:

 I strongly reject this claim, due to the lack to evidence. I 
 encounter no apocalypse scenario when it comes to unable to 
 named arguments in the C# community which you can not opt it 
 out.

 Alex
* I encounter no apocalypse scenario when it comes to unable to opt out named arguments in the C# community. Grammar fix.
Jun 06
prev sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 20:22:17 UTC, 12345swordy wrote:
 On Thursday, 6 June 2019 at 20:10:06 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 20:04:09 UTC, 12345swordy wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler 
 wrote:
 [...]
This has been brought up in the discussion regarding named arguments for DIP1020 (more specifically the named attribute) and so far I am not convinced that this is an issue that needs to be address, and found it be be overblown given that we have powerful rename tools at this day of age. Having it "opt-in" have it own downsides as the users have to request library developers to add the capability to their libraries. Among many other issues that were brought up and discuss with "opt-in"ing DIP1020. Alex
Rename tools are irrelevant as they only work when you're in a single project.
No, they are not irrelevant, that what C# developers such as myself use when the named argument name has been change.
You missed the point. I'm talking about libraries (like druntime and phobos) now have all their function parameters exposed. If they need to change them, you can't use a replace tool on every single D project in the world that depends on DRuntime and Phobos. Thus, replace tools are irrelevant in this case.
  Exposing the parameters names of every function would mean 
 the we would pretty much need to keep all the parameter names 
 in every function in druntime/phobos, otherwise we would break 
 compatibility.
We have a deprecated attribute for a very good reason.
Yes there are solutions, but you have to weigh the cost with the benefit. There are not that many functions that will benefit from using named parameters. I'd guess around 15% of all functions would use them, and you're breaking encapsulation with all 100% of functions to accommodate the 15%. It's a high cost compared to the benefit. However, if you make it "opt-in", then you don't have to pay that high cost.
 Far to high of a cost just to allow some cases to be more 
 readable.
I strongly reject this claim, due to the lack to evidence. I encounter no apocalypse scenario when it comes to unable to named arguments in the C# community which you can not opt it out.
It's the same argument for having private fields in classes and structs. If you don't understand the benefits of encapsulation then I'm not sure what to say. The more coupling and internals you expose, the more opportunity to break your interface. And because functions are such a big part of D, you're making the language overall much more brittle than it was before.
Jun 06
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 6 June 2019 at 22:19:46 UTC, Jonathan Marler wrote:
 If they need to change them
Why would they need to change the name of a function argument anyway? Note that the name is already exposed in the documentation too, as well as by existing reflection (I, among others, have written named param libraries already, for example).
 I'd guess around 15% of all functions would use them
I'd probably not use it myself so I'm meh on having it in the language... but I don't think the breakage is a big deal. You can just not use it in your code and be protected against arbitrary changes. Though if the name changes, it might indicate a change in meaning of the param too, so maybe breakage is a good thing.
Jun 06
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 22:26:57 UTC, Adam D. Ruppe wrote:
 On Thursday, 6 June 2019 at 22:19:46 UTC, Jonathan Marler wrote:
 If they need to change them
Why would they need to change the name of a function argument anyway?
Seems like a silly question doesn't it? Have you ever changed the name of an argument in a library? Have you ever changed the name of private field in a struct/class? What you're saying is that functions should not have any privacy/encapsulation when it comes to parameters names. Do you also think structs and classes should not have the private modifier?
 Note that the name is already exposed in the documentation too, 
 as well as by existing reflection (I, among others, have 
 written named param libraries already, for example).

 I'd guess around 15% of all functions would use them
I'd probably not use it myself so I'm meh on having it in the language... but I don't think the breakage is a big deal. You can just not use it in your code and be protected against arbitrary changes.
Again...do you also apply this same argument to having private fields in structs/classes?
 Though if the name changes, it might indicate a change in 
 meaning of the param too, so maybe breakage is a good thing.
So in that case, you would make the parameter "public" so you could expose a change in semantics. I'm not saying we shouldn't have named arguments, I'm saying it should be "opt-in".
Jun 06
next sibling parent Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 22:38:53 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 22:26:57 UTC, Adam D. Ruppe wrote:
 On Thursday, 6 June 2019 at 22:19:46 UTC, Jonathan Marler 
 wrote:
 If they need to change them
Why would they need to change the name of a function argument anyway?
Seems like a silly question doesn't it? Have you ever changed the name of an argument in a library? Have you ever changed the name of private field in a struct/class? What you're saying is that functions should not have any privacy/encapsulation when it comes to parameters names. Do you also think structs and classes should not have the private modifier?
 Note that the name is already exposed in the documentation 
 too, as well as by existing reflection (I, among others, have 
 written named param libraries already, for example).

 I'd guess around 15% of all functions would use them
I'd probably not use it myself so I'm meh on having it in the language... but I don't think the breakage is a big deal. You can just not use it in your code and be protected against arbitrary changes.
Again...do you also apply this same argument to having private fields in structs/classes?
 Though if the name changes, it might indicate a change in 
 meaning of the param too, so maybe breakage is a good thing.
So in that case, you would make the parameter "public" so you could expose a change in semantics. I'm not saying we shouldn't have named arguments, I'm saying it should be "opt-in".
I do see some weaknesses with the "opt-in" approach. The first one being that once a library decides to "opt-in", depending on how it's done, it may break that library from being compile-able by older compilers. Also if named parameters were more useful, say around 50% of all functions, I would probably lean towards saying that we could sacrifice encapsulation and just have everything opt-in by default. But because I think it will be needed more rarely, "opt-in" seems to make sense to me to preserve encapsulation of parameter names.
Jun 06
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07.06.19 00:38, Jonathan Marler wrote:
 I'd probably not use it myself so I'm meh on having it in the 
 language... but I don't think the breakage is a big deal. You can just 
 not use it in your code and be protected against arbitrary changes.
Again...do you also apply this same argument to having private fields in structs/classes?
This analogy has no merit. Why would function arguments need a notion of encapsulation? They are part of the interface by definition.
Jun 06
prev sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Thursday, 6 June 2019 at 22:19:46 UTC, Jonathan Marler wrote:
 You missed the point.
No, you are the one who is missing the point here. Point being is that fix breakage cause by name change is quick, simple and easy. The tools are advance enough for quick fixes.
  There are not that many functions that will benefit from using 
 named parameters.
Says who!? You? Readability matters a lot to me. I hate C++, because it is so bad at readability.
 However, if you make it "opt-in", then you don't have to pay 
 that high cost.
Sorry I don't believe that it is a "high cost". Tools are quite good enough to compensate the change.
 Far to high of a cost just to allow some cases to be more 
 readable.
I strongly reject this claim, due to the lack to evidence. I encounter no apocalypse scenario when it comes to unable to named arguments in the C# community which you can not opt it out.
It's the same argument for having private fields in classes and structs.
No, they are not the same thing! Encapsulation involves information hiding, and confidentiality. It makes no sense to hide the names of the function arguments when exposed to the public. I am not going to repeat of what I said months ago regarding this. I have said my arguments on why making it opt-in is a terrible idea. Not going to rehash it again. Alex
Jun 06
prev sibling parent reply Exil <Exil gmall.com> writes:
On Thursday, 6 June 2019 at 20:10:06 UTC, Jonathan Marler wrote:
 Far to high of a cost just to allow some cases to be more 
 readable.  However, if you make it opt-in, then you don't have 
 to pay that cost for EVERY function, you only increase coupling 
 in the cases that make sense.
Making it optional makes it useless. Name the programming languages that implement named parameters this way, and I'll give a giant list of ones that don't. You can make this exact argument for basically structs and everything else. When you use a library you are at the mercy of it's owner. I've seen some people maintain an API that just literally changed the style so basically every single line that used that API now had to be updated. It was a minor version too 3.0 -> 3.1. Let the user decide when those cases are for themselves, and they do so knowing the risk, like with everything else they may have to update their code to match. There's already enough attributes, we shouldn't be adding more needlessly. I don't think this is a good enough reason to.
Jun 06
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 20:25:32 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 20:10:06 UTC, Jonathan Marler wrote:
 Far to high of a cost just to allow some cases to be more 
 readable.  However, if you make it opt-in, then you don't have 
 to pay that cost for EVERY function, you only increase 
 coupling in the cases that make sense.
Making it optional makes it useless. Name the programming languages that implement named parameters this way, and I'll give a giant list of ones that don't. You can make this exact argument for basically structs and everything else.
Yes I am making the same argument as for structs/classes. Structs and classes can "opt-in" and "opt-out" to exposing their fields. Saying that all function parameter names should be exposed and coupled to the caller is like saying we shouldn't have private fields in structs and classes.
 When you use a library you are at the mercy of it's owner. I've 
 seen some people maintain an API that just literally changed 
 the style so basically every single line that used that API now 
 had to be updated.
Even more reason not expose all the parameter names of all the functions in their library. If the library owner changes any of their parameters names, they have broken compatibility with their library. This increases the opportunity for breakage dramatically. That's the power and benefit of encapsulation, being able to change the internals without breaking your external facing API.
 There's already enough attributes, we shouldn't be adding more 
 needlessly. I don't think this is a good enough reason to.
I didn't say we should add an attribute. You're now demonstrating the "straw man fallacy" (https://en.wikipedia.org/wiki/Straw_man).
Jun 06
parent reply Exil <Exil gmall.com> writes:
On Thursday, 6 June 2019 at 22:35:31 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 20:25:32 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 20:10:06 UTC, Jonathan Marler 
 wrote:
 Far to high of a cost just to allow some cases to be more 
 readable.  However, if you make it opt-in, then you don't 
 have to pay that cost for EVERY function, you only increase 
 coupling in the cases that make sense.
Making it optional makes it useless. Name the programming languages that implement named parameters this way, and I'll give a giant list of ones that don't. You can make this exact argument for basically structs and everything else.
Yes I am making the same argument as for structs/classes. Structs and classes can "opt-in" and "opt-out" to exposing their fields. Saying that all function parameter names should be exposed and coupled to the caller is like saying we shouldn't have private fields in structs and classes.
That doesn't make any sense. To make a function parameter "private" that would mean the user wouldn't be able to pass in a value to it. They are already public, they just need a name now. Why aren't you proposing this instead then ? void foo(private int a, public int b) { } Cause it doesn't make sense, not one wants to deal with that address complexity because it provides zero benefit. The only benefit you get from having names be optional is that library maintainers can screw over their user base if they want to use the feature or not. This does not solve anything by making it optional. Every issue you can have with it not being optional is already a problem today with existing features, and there's no solution to it a side from governing people that use D.
 When you use a library you are at the mercy of it's owner. 
 I've seen some people maintain an API that just literally 
 changed the style so basically every single line that used 
 that API now had to be updated.
Even more reason not expose all the parameter names of all the functions in their library. If the library owner changes any of their parameters names, they have broken compatibility with their library. This increases the opportunity for breakage dramatically. That's the power and benefit of encapsulation, being able to change the internals without breaking your external facing API.
That power is entirely depending on the person writing it. If the maintainer wants to keep backwards compatibility with named arguments it is very easy to do so. This is NOT encapsulation, you can still access parameters. Making it optional won't make maintainers be good maintainers, it will just make the users suffer and avoid the feature for its uselessness.
 There's already enough attributes, we shouldn't be adding more 
 needlessly. I don't think this is a good enough reason to.
I didn't say we should add an attribute. You're now demonstrating the "straw man fallacy" (https://en.wikipedia.org/wiki/Straw_man).
What the, this isn't even the main argument and your pulling that card? Come on now. I would be interested in hearing how you will mark one function as optional and another as not optional though. Someone suggested named, I have yet to hear anything better from you.
Jun 06
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 23:08:56 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 22:35:31 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 20:25:32 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 20:10:06 UTC, Jonathan Marler 
 wrote:
 Far to high of a cost just to allow some cases to be more 
 readable.  However, if you make it opt-in, then you don't 
 have to pay that cost for EVERY function, you only increase 
 coupling in the cases that make sense.
Making it optional makes it useless. Name the programming languages that implement named parameters this way, and I'll give a giant list of ones that don't. You can make this exact argument for basically structs and everything else.
Yes I am making the same argument as for structs/classes. Structs and classes can "opt-in" and "opt-out" to exposing their fields. Saying that all function parameter names should be exposed and coupled to the caller is like saying we shouldn't have private fields in structs and classes.
That doesn't make any sense. To make a function parameter "private" that would mean the user wouldn't be able to pass in a value to it.
That's not the meaning I proposed. I proposed that public exposes the "name" of the function parameter. You're "straw manning" again, please look that one up. Understand what I'm saying before you respond.
 Cause it doesn't make sense, not one wants to deal with that 
 address complexity because it provides zero benefit.
Encapsulation = Zero Benefit? Well I can see we're not going to agree here :)
 The only benefit you get from having names be optional is that 
 library maintainers can screw over their user base if they want 
 to use the feature or not.
Again, the benefit is Encapsulation.
 When you use a library you are at the mercy of it's owner. 
 I've seen some people maintain an API that just literally 
 changed the style so basically every single line that used 
 that API now had to be updated.
Even more reason not expose all the parameter names of all the functions in their library. If the library owner changes any of their parameters names, they have broken compatibility with their library. This increases the opportunity for breakage dramatically. That's the power and benefit of encapsulation, being able to change the internals without breaking your external facing API.
That power is entirely depending on the person writing it. If the maintainer wants to keep backwards compatibility with named arguments it is very easy to do so. This is NOT encapsulation, you can still access parameters. Making it optional won't make maintainers be good maintainers, it will just make the users suffer and avoid the feature for its uselessness.
You seem to be confusing what I said. I didn't say the parameters are encapsulated...that doesn't make any sense. I'm talking about encapsulating the 'names' of the parameters. I think once you understand the distinction you'll see you're response here doesn't make much sense.
 There's already enough attributes, we shouldn't be adding 
 more needlessly. I don't think this is a good enough reason 
 to.
I didn't say we should add an attribute. You're now demonstrating the "straw man fallacy" (https://en.wikipedia.org/wiki/Straw_man).
What the, this isn't even the main argument and your pulling that card? Come on now. I would be interested in hearing how you will mark one function as optional and another as not optional though. Someone suggested named, I have yet to hear anything better from you.
You just need a way to distinguish named from unnamed. Opt-in and Opt out. You could do so by putting all your named arguments in a struct and supporting some caller syntax to expand arguments into that struct. You could use tuples, you could use a special type wrapper. And yes, you could use an attribute like "public", but you don't have too is the point. Keep in mind that I'm not trying to say that you don't have any points here. You are correct that having to opt-in means you have to depend on your libraries to opt-in to using named arguments before you can use them. That's a valid point. I'm just weighing the pros and cons here. I see a big con to enabling this by default for every function in D. I see a small benefit from the feature altogether, as it's only useful for a small percentage of functions. We can argue over how big/small those factors are, but I hope we agree that they are factors and that encapsulation matters and is important. We can argue over the value of encapsulating parameter names, but you shouldn't dismiss it altogether. A good scientist weighs all the factors without any bias, whether or not they agree with his/her initial hypothesis. Listen to what others are saying and consider it. We're not at war trying to "beat" each other, we're on the same team trying to make D better for everyone.
Jun 06
next sibling parent reply Exil <Exil gmall.com> writes:
On Thursday, 6 June 2019 at 23:36:11 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 23:08:56 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 22:35:31 UTC, Jonathan Marler 
 wrote:
 On Thursday, 6 June 2019 at 20:25:32 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 20:10:06 UTC, Jonathan Marler 
 wrote:
 Far to high of a cost just to allow some cases to be more 
 readable.  However, if you make it opt-in, then you don't 
 have to pay that cost for EVERY function, you only increase 
 coupling in the cases that make sense.
Making it optional makes it useless. Name the programming languages that implement named parameters this way, and I'll give a giant list of ones that don't. You can make this exact argument for basically structs and everything else.
Yes I am making the same argument as for structs/classes. Structs and classes can "opt-in" and "opt-out" to exposing their fields. Saying that all function parameter names should be exposed and coupled to the caller is like saying we shouldn't have private fields in structs and classes.
That doesn't make any sense. To make a function parameter "private" that would mean the user wouldn't be able to pass in a value to it.
That's not the meaning I proposed. I proposed that public exposes the "name" of the function parameter. You're "straw manning" again, please look that one up. Understand what I'm saying before you respond.
It's what private currently means. You are misunderstanding what I am saying and throwing around strawman like it applies. Encapsulation/private/public do not relate at all to what you are suggesting.
 Cause it doesn't make sense, not one wants to deal with that 
 address complexity because it provides zero benefit.
Encapsulation = Zero Benefit? Well I can see we're not going to agree here :)
This is not encapsulation. You are conflating the two. Talk about strawman...
 The only benefit you get from having names be optional is that 
 library maintainers can screw over their user base if they 
 want to use the feature or not.
Again, the benefit is Encapsulation.
It is not encapsulation.
 When you use a library you are at the mercy of it's owner. 
 I've seen some people maintain an API that just literally 
 changed the style so basically every single line that used 
 that API now had to be updated.
Even more reason not expose all the parameter names of all the functions in their library. If the library owner changes any of their parameters names, they have broken compatibility with their library. This increases the opportunity for breakage dramatically. That's the power and benefit of encapsulation, being able to change the internals without breaking your external facing API.
That power is entirely depending on the person writing it. If the maintainer wants to keep backwards compatibility with named arguments it is very easy to do so. This is NOT encapsulation, you can still access parameters. Making it optional won't make maintainers be good maintainers, it will just make the users suffer and avoid the feature for its uselessness.
You seem to be confusing what I said. I didn't say the parameters are encapsulated...that doesn't make any sense. I'm talking about encapsulating the 'names' of the parameters. I think once you understand the distinction you'll see you're response here doesn't make much sense.
And you are going on and on about encapsulation... I understand what you are saying. That is not encapsulation, and what you are proposing is not useful. It prevents a useful feature from being used, if API maintainers don't want to maintain it, then they don't have to. Just like everything else. But then no one will use their API, and/or people will complain and it will be fixed.
 There's already enough attributes, we shouldn't be adding 
 more needlessly. I don't think this is a good enough reason 
 to.
I didn't say we should add an attribute. You're now demonstrating the "straw man fallacy" (https://en.wikipedia.org/wiki/Straw_man).
What the, this isn't even the main argument and your pulling that card? Come on now. I would be interested in hearing how you will mark one function as optional and another as not optional though. Someone suggested named, I have yet to hear anything better from you.
You just need a way to distinguish named from unnamed. Opt-in and Opt out. You could do so by putting all your named arguments in a struct and supporting some caller syntax to expand arguments into that struct. You could use tuples, you could use a special type wrapper. And yes, you could use an attribute like "public", but you don't have too is the point.
Those all sound like terrible ideas. I need an extra struct to be able to use named and unnamed functions? So now named parameters dictate the design? I can only imagine the additional problems this would add. A special type wrapper might be worse than an extra attribute.
 I'm just weighing the pros and cons here.  I see a big con to 
 enabling this by default for every function in D.  I see a 
 small benefit from the feature altogether, as it's only useful 
 for a small percentage of functions.
It doesn't matter what percentage. That's the thing, you might say this section of is more important and should use named parameters. But I disagree, and I think this other section should have named parameters. But you are the library maintainer, so you make your choice and you chose to ignore mine. Now I use your library and I am restricted to which functions I can use a language feature on. I can't use the language feature where I want to because of the maintainer's opinion. struct A { private: int a; } A a; a.a = 10; // error can't do it void foo( int value ); foo( value: 10 ); // error not defined to use named parameters foo( 10 ); // functionally the same The whole idea of "encapsulating" the variable name is completely bonkers to me. It's a feature that is mislabeling something as encapsulation and is trying to shoehorn it is with statements on the basis that "encapsulation" can't be bad. It is when you don't know what it is or why it is useful.
Jun 06
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 7 June 2019 at 02:44:19 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 23:36:11 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 23:08:56 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 22:35:31 UTC, Jonathan Marler 
 wrote:
 On Thursday, 6 June 2019 at 20:25:32 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 20:10:06 UTC, Jonathan Marler 
 wrote:
 Far to high of a cost just to allow some cases to be more 
 readable.  However, if you make it opt-in, then you don't 
 have to pay that cost for EVERY function, you only 
 increase coupling in the cases that make sense.
Making it optional makes it useless. Name the programming languages that implement named parameters this way, and I'll give a giant list of ones that don't. You can make this exact argument for basically structs and everything else.
Yes I am making the same argument as for structs/classes. Structs and classes can "opt-in" and "opt-out" to exposing their fields. Saying that all function parameter names should be exposed and coupled to the caller is like saying we shouldn't have private fields in structs and classes.
That doesn't make any sense. To make a function parameter "private" that would mean the user wouldn't be able to pass in a value to it.
That's not the meaning I proposed. I proposed that public exposes the "name" of the function parameter. You're "straw manning" again, please look that one up. Understand what I'm saying before you respond.
It's what private currently means. You are misunderstanding what I am saying and throwing around strawman like it applies. Encapsulation/private/public do not relate at all to what you are suggesting.
I suggested that we could re-use the `public` keyword to allow a function to expose their parameter names to the caller. It works because `public` currently has no meaning when you apply it to function parameters. But you seem to be assigning the `private` modifier a meaning to function parameters that doesn't exist and that I didn't suggest, hence you are straw-manning my idea. And the reason why this is "encapsulation" is because you are "encapsulating" the names of parameters from the caller, meaning that the library is free to change them without breaking compatibility. Just like a library owner knows they can change their private field names without breaking compatibility with their library.
 Cause it doesn't make sense, not one wants to deal with that 
 address complexity because it provides zero benefit.
Encapsulation = Zero Benefit? Well I can see we're not going to agree here :)
This is not encapsulation. You are conflating the two. Talk about strawman...
"conflating the two"? Conflating encapsulation and what else? Encapsulation is the only point I'm making here.
 When you use a library you are at the mercy of it's owner. 
 I've seen some people maintain an API that just literally 
 changed the style so basically every single line that used 
 that API now had to be updated.
Even more reason not expose all the parameter names of all the functions in their library. If the library owner changes any of their parameters names, they have broken compatibility with their library. This increases the opportunity for breakage dramatically. That's the power and benefit of encapsulation, being able to change the internals without breaking your external facing API.
That power is entirely depending on the person writing it. If the maintainer wants to keep backwards compatibility with named arguments it is very easy to do so. This is NOT encapsulation, you can still access parameters. Making it optional won't make maintainers be good maintainers, it will just make the users suffer and avoid the feature for its uselessness.
You seem to be confusing what I said. I didn't say the parameters are encapsulated...that doesn't make any sense. I'm talking about encapsulating the 'names' of the parameters. I think once you understand the distinction you'll see you're response here doesn't make much sense.
And you are going on and on about encapsulation... I understand what you are saying. That is not encapsulation, and what you are proposing is not useful. It prevents a useful feature from being used, if API maintainers don't want to maintain it, then they don't have to. Just like everything else. But then no one will use their API, and/or people will complain and it will be fixed.
There's an expression for what I just read in this last paragraph. "Talking out of both sides of your mouth". You said "This is not encapsulation" and then immediately afterwards said that if an API maintainer doesn't maintain this feature, then it will break their API and users won't use it. If you can't understand why you contradicted yourself here, there's really nothing I can do.
 There's already enough attributes, we shouldn't be adding 
 more needlessly. I don't think this is a good enough reason 
 to.
I didn't say we should add an attribute. You're now demonstrating the "straw man fallacy" (https://en.wikipedia.org/wiki/Straw_man).
What the, this isn't even the main argument and your pulling that card? Come on now. I would be interested in hearing how you will mark one function as optional and another as not optional though. Someone suggested named, I have yet to hear anything better from you.
You just need a way to distinguish named from unnamed. Opt-in and Opt out. You could do so by putting all your named arguments in a struct and supporting some caller syntax to expand arguments into that struct. You could use tuples, you could use a special type wrapper. And yes, you could use an attribute like "public", but you don't have too is the point.
Those all sound like terrible ideas. I need an extra struct to be able to use named and unnamed functions? So now named parameters dictate the design? I can only imagine the additional problems this would add. A special type wrapper might be worse than an extra attribute.
 I'm just weighing the pros and cons here.  I see a big con to 
 enabling this by default for every function in D.  I see a 
 small benefit from the feature altogether, as it's only useful 
 for a small percentage of functions.
It doesn't matter what percentage. That's the thing, you might say this section of is more important and should use named parameters. But I disagree, and I think this other section should have named parameters. But you are the library maintainer, so you make your choice and you chose to ignore mine. Now I use your library and I am restricted to which functions I can use a language feature on. I can't use the language feature where I want to because of the maintainer's opinion. struct A { private: int a; } A a; a.a = 10; // error can't do it void foo( int value ); foo( value: 10 ); // error not defined to use named parameters foo( 10 ); // functionally the same The whole idea of "encapsulating" the variable name is completely bonkers to me. It's a feature that is mislabeling something as encapsulation and is trying to shoehorn it is with statements on the basis that "encapsulation" can't be bad. It is when you don't know what it is or why it is useful.
I'm very confused why you keep saying that hiding parameter names isn't "encapsulation". The point is that if you expose the parameters names of all functions, you've increased the coupling between all functions and their callers and therefore decreased encapsulation. If you want to say that parameters names are not very useful to encapsulate, then that's fine, you can have that opinion. But saying that it's not encapsulation at all is demonstrably false. You also said the "percentage didn't matter", which may be the case for you but not for me. For me, the percentage of functions that would benefit from this tells me whether it should be "opt-in", "opt-out" or "always on" (the current DIP has proposed "always on"). If there is no downside to enabling them, then I would be fine with "always on", even if there usefulness is low. But because I do see a big downside, and I think only about 15% of functions can benefit from it, it seems to me an "opt-in" option makes sense here. Note here that I could also be convinced otherwise, but saying "this is not encapsulation" is not a convincing argument. One thing that would be beneficial to discuss is what that percentage is. I've actually proposed named parameters be added to another language (zig) here: https://github.com/ziglang/zig/issues/479 I came up with a list of cases when named arguments are helpful: 1. flag type parameters add(1, 2, true); // what is true for? add(1, 2, checkOverflow=true); // there we go However in D, this one can be mitigated with Flag. It's a bit less convenient though. 2. if the parameter is a "unit type" like seconds/meters sleep(1); // is this seconds or milliseconds or what? sleep(seconds = 1); // much better D also has ways to mitigate this one as well, such as abstract types like Duration. But like flag, these can be less convenient. 3. if the function takes multiple parameters of the same type whose order is important but not clear can't think of a good example for this one at the moment By my estimate the percentage of functions that fit any of these 3 criteria is around 15%. This isn't backed by any real data, just an estimate. I would love to see actual data on this, if someone wants to go through some druntime/phobos modules and count how many functions would benefit from named arguments. And my criteria list could also be incomplete, I'm sure there are other cases where named parameters could be useful. Please let me know if you can think of any more. And if it turns out the percentage is much higher than my estimate, then I might change my mind and say that decreasing encapsulation is worth the benefit of having named parameters "always on".
Jun 06
parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Friday, 7 June 2019 at 03:52:24 UTC, Jonathan Marler wrote:
 By my estimate the percentage of functions that fit any of 
 these 3 criteria is around 15%. This isn't backed by any real 
 data, just an estimate.  I would love to see actual data on 
 this, if someone wants to go through some druntime/phobos 
 modules and count how many functions would benefit from named 
 arguments.  And my criteria list could also be incomplete, I'm 
 sure there are other cases where named parameters could be 
 useful.  Please let me know if you can think of any more.  And 
 if it turns out the percentage is much higher than my estimate, 
 then I might change my mind and say that decreasing 
 encapsulation is worth the benefit of having named parameters 
 "always on".
D has features that are useful for a *lot* less than 15% of cases. If you think named parameters are so harmful that 15% is too low a rate to bring them in, then you basically dislike named parameters as a feature. But this is not a disagreement on merits - the things you dislike *are* the things that I like about named parameters. I think we have to separate "I don't like these parts of this feature" and "I think these parts don't *work*". The very notion of "Named Arguments Lite" is in my opinion the consequence of trying to appeal to people who just don't find named arguments appealing. I think we need to separate "problems with named arguments" and "problems with this DIP for named arguments" (of which there's still plenty). If you think that named arguments, or rather opt-out named arguments, are a bad idea, there should be a separate language design thread to debate that question.
Jun 06
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 7 June 2019 at 05:18:51 UTC, FeepingCreature wrote:
 On Friday, 7 June 2019 at 03:52:24 UTC, Jonathan Marler wrote:
 By my estimate the percentage of functions that fit any of 
 these 3 criteria is around 15%. This isn't backed by any real 
 data, just an estimate.  I would love to see actual data on 
 this, if someone wants to go through some druntime/phobos 
 modules and count how many functions would benefit from named 
 arguments.  And my criteria list could also be incomplete, I'm 
 sure there are other cases where named parameters could be 
 useful.  Please let me know if you can think of any more.  And 
 if it turns out the percentage is much higher than my 
 estimate, then I might change my mind and say that decreasing 
 encapsulation is worth the benefit of having named parameters 
 "always on".
D has features that are useful for a *lot* less than 15% of cases. If you think named parameters are so harmful that 15% is too low a rate to bring them in, then you basically dislike named parameters as a feature.
I'm not sure where you got that, I never said I didn't want named parameters. I do want to bring named parameters in even though I only think they apply to 15% of cases. I'm just pointing out a reason for making them "opt-in" instead of "always on" with no way to disable them. I think there are other proposals that provide the same benefits without the drawbacks. Walter's proposal may be one, Timon's tuple proposal should be considered as well to make sure we don't design a feature that won't work if we decide to implement tuples.
 But this is not a disagreement on merits - the things you 
 dislike *are* the things that I like about named parameters. I 
 think we have to separate "I don't like these parts of this 
 feature" and "I think these parts don't *work*".
I think there are pros and cons to exposing all parameters names to all callers. The big con is that it adds extra coupling between every function and caller that in the majority of cases is not beneficial (at least by my estimate, having data will show whether or not it is actually the majority). But there are benefits to enabling named parameters for all functions such as allowing the feature to be used without changing libraries, and it's backwards compatible. I can see the pros and the cons, I'm just pointing out the con, but I can see where you're coming from if you think the pros outweigh the con. What some people on this thread are saying is that the CON doesn't exist, so I'm focusing on explaining why it does exist which probably makes it sound like I don't want the feature at all.
 The very notion of "Named Arguments Lite" is in my opinion the 
 consequence of trying to appeal to people who just don't find 
 named arguments appealing.

 I think we need to separate "problems with named arguments" and 
 "problems with this DIP for named arguments" (of which there's 
 still plenty). If you think that named arguments, or rather 
 opt-out named arguments, are a bad idea, there should be a 
 separate language design thread to debate that question.
Well this DIP isn't even "opt-out", at least for the function definition. If I want to keep my parameters names private so that I can change them without breaking compatibility, I have no way to do it. It's like not having a way to make fields private in a struct or class. Though to be fair, exposing field names vs parameters names are not the same thing, but the drawback shouldn't be dismissed. Instead it should be analyzed and weighed against everything else. But you are right that this DIP should not be the "make or break" for named parameters, and I don't think anyone is saying it is. I'm just pointing out a flaw with this particular DIP, not with named arguments in general.
Jun 06
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 7 June 2019 at 05:37:25 UTC, Jonathan Marler wrote:
 I think there are pros and cons to exposing all parameters 
 names to all callers.
We already have this though.
 If I want to keep my parameters names private so that I can 
 change them without breaking compatibility, I have no way to do 
 it.
Actually, you could use a .di file. The parameter names are not in the function mangle (and even if they were, it could be handled, like the extern(objective-c) selector thing), so you can call it one thing in your code and something else in the distributed interface file. You could also use public names on the outside and immediately alias them to something else inside a function. It is just, again, we *already have* the names exposed (and already have ways to ignore them). So it isn't taking something previously totally hidden and opening it.
Jun 07
parent Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 7 June 2019 at 11:30:02 UTC, Adam D. Ruppe wrote:
 On Friday, 7 June 2019 at 05:37:25 UTC, Jonathan Marler wrote:
 I think there are pros and cons to exposing all parameters 
 names to all callers.
We already have this though.
I think exposed via reflection vs exposed via direct access makes a difference. Even if private fields are exposed via reflection, there's still an understanding that the type is still "compatible" with other versions of itself that reorganize those private fields.
Jun 07
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07.06.19 01:36, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 23:08:56 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 22:35:31 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 20:25:32 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 20:10:06 UTC, Jonathan Marler wrote:
 Far to high of a cost just to allow some cases to be more 
 readable.  However, if you make it opt-in, then you don't have to 
 pay that cost for EVERY function, you only increase coupling in the 
 cases that make sense.
Making it optional makes it useless. Name the programming languages that implement named parameters this way, and I'll give a giant list of ones that don't. You can make this exact argument for basically structs and everything else.
Yes I am making the same argument as for structs/classes. Structs and classes can "opt-in" and "opt-out" to exposing their fields.  Saying that all function parameter names should be exposed and coupled to the caller is like saying we shouldn't have private fields in structs and classes.
That doesn't make any sense. To make a function parameter "private" that would mean the user wouldn't be able to pass in a value to it.
That's not the meaning I proposed.  I proposed that public exposes the "name" of the function parameter.  You're "straw manning" again,
No, he's just not arguing against the aspect of your idea that you think he is. You are the one setting up the straw man.
 please look that one up.  Understand what I'm saying before you respond.
 ...
That's a pretty hard constraint to satisfy, considering that you are not making any sense.
 Cause it doesn't make sense, not one wants to deal with that address 
 complexity because it provides zero benefit.
Encapsulation = Zero Benefit? Well I can see we're not going to agree here :) ...
His point was that hiding argument names is not "encapsulation". You are arguing against a straw man. Note that mentioning fallacies by name is actually rarely useful.
 The only benefit you get from having names be optional is that library 
 maintainers can screw over their user base if they want to use the 
 feature or not.
Again, the benefit is Encapsulation.
Well, let's look at the facts: - Parameter names are already exposed, and changing parameter names can already break third-party code: https://dlang.org/phobos/std_traits.html#ParameterIdentifierTuple No "encapsulation" for you. (Whatever that's supposed to mean.) - It is possible to not name parameters (an alternative way is to use *.di files): import std.traits; int add(int, int){ return _param_0+_param_1; } void main(){ assert(add(1,2)==3); } I guess that's what you would call "encapsulation". I.e., if you want to not expose any parameter names, you have the means to do so. Let's call those two ways to declare parameters public and private. What named arguments allow you to do is to actually refer to the public parameters by name. If we had structs with public and private fields, there was no field access (e.f) syntax and you could only access public fields by index, would you also argue that this is a good thing, even if there was already a __trait to get the index of a field from its name and vice-versa?
Jun 06
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07.06.19 04:51, Timon Gehr wrote:
 argument names
parameter names
Jun 06
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07.06.19 04:51, Timon Gehr wrote:
 
 import std.traits;
Unnecessary import. I should go to sleep.
Jun 06
prev sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 7 June 2019 at 02:51:16 UTC, Timon Gehr wrote:
 On 07.06.19 01:36, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 23:08:56 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 22:35:31 UTC, Jonathan Marler 
 wrote:
 On Thursday, 6 June 2019 at 20:25:32 UTC, Exil wrote:
 [...]
Yes I am making the same argument as for structs/classes. Structs and classes can "opt-in" and "opt-out" to exposing their fields.  Saying that all function parameter names should be exposed and coupled to the caller is like saying we shouldn't have private fields in structs and classes.
That doesn't make any sense. To make a function parameter "private" that would mean the user wouldn't be able to pass in a value to it.
That's not the meaning I proposed.  I proposed that public exposes the "name" of the function parameter.  You're "straw manning" again,
No, he's just not arguing against the aspect of your idea that you think he is. You are the one setting up the straw man.
He said "To make a function parameter 'private' that would mean the user wouldn't be able to pass in a value to it". My idea had nothing to do with preventing callers from passing values to arguments, hence why he is straw manning me.
 The only benefit you get from having names be optional is 
 that library maintainers can screw over their user base if 
 they want to use the feature or not.
Again, the benefit is Encapsulation.
Well, let's look at the facts: - Parameter names are already exposed, and changing parameter names can already break third-party code: https://dlang.org/phobos/std_traits.html#ParameterIdentifierTuple No "encapsulation" for you. (Whatever that's supposed to mean.) - It is possible to not name parameters (an alternative way is to use *.di files): import std.traits; int add(int, int){ return _param_0+_param_1; } void main(){ assert(add(1,2)==3); } I guess that's what you would call "encapsulation". I.e., if you want to not expose any parameter names, you have the means to do so. Let's call those two ways to declare parameters public and private. What named arguments allow you to do is to actually refer to the public parameters by name. If we had structs with public and private fields, there was no field access (e.f) syntax and you could only access public fields by index, would you also argue that this is a good thing, even if there was already a __trait to get the index of a field from its name and vice-versa?
Hmmm that's a good point, I suppose they are already exposed to the caller. However, I believe private fields in structs/classes have the same problem. You can still access those fields with some fancy reflection, but I don't think that means we should get rid of private fields just because we can still access them through reflection. Do you?
Jun 06
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07.06.19 05:10, Jonathan Marler wrote:
 On Friday, 7 June 2019 at 02:51:16 UTC, Timon Gehr wrote:
 On 07.06.19 01:36, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 23:08:56 UTC, Exil wrote:
 On Thursday, 6 June 2019 at 22:35:31 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 20:25:32 UTC, Exil wrote:
 [...]
Yes I am making the same argument as for structs/classes. Structs and classes can "opt-in" and "opt-out" to exposing their fields. Saying that all function parameter names should be exposed and coupled to the caller is like saying we shouldn't have private fields in structs and classes.
That doesn't make any sense. To make a function parameter "private" that would mean the user wouldn't be able to pass in a value to it.
That's not the meaning I proposed.  I proposed that public exposes the "name" of the function parameter.  You're "straw manning" again,
No, he's just not arguing against the aspect of your idea that you think he is. You are the one setting up the straw man.
He said "To make a function parameter 'private' that would mean the user wouldn't be able to pass in a value to it".  My idea had nothing to do with preventing callers from passing values to arguments, hence why he is straw manning me. ...
Reductio ad absurdum is not per se a straw man fallacy, even if you disagree with/misunderstand the reasoning/definitions/values that lead to the ridiculous conclusion.
 The only benefit you get from having names be optional is that 
 library maintainers can screw over their user base if they want to 
 use the feature or not.
Again, the benefit is Encapsulation.
Well, let's look at the facts: - Parameter names are already exposed, and changing parameter names can already break third-party code: https://dlang.org/phobos/std_traits.html#ParameterIdentifierTuple No "encapsulation" for you. (Whatever that's supposed to mean.) - It is possible to not name parameters (an alternative way is to use *.di files): import std.traits; int add(int, int){     return _param_0+_param_1; } void main(){     assert(add(1,2)==3); } I guess that's what you would call "encapsulation". I.e., if you want to not expose any parameter names, you have the means to do so. Let's call those two ways to declare parameters public and private. What named arguments allow you to do is to actually refer to the public parameters by name. If we had structs with public and private fields, there was no field access (e.f) syntax and you could only access public fields by index, would you also argue that this is a good thing, even if there was already a __trait to get the index of a field from its name and vice-versa?
Hmmm that's a good point, I suppose they are already exposed to the caller.  However, I believe private fields in structs/classes have the same problem.  You can still access those fields with some fancy reflection, but I don't think that means we should get rid of private fields just because we can still access them through reflection.  Do you?
I don't particularly care, because there are other ways to restrict your public interface. Anyway, there are other pertinent points. As I said before, the analogy to _private_ fields actually does not have a lot of merit. You don't make your fields private just to be able to rename them, but to be able to completely reorganize your implementation, removing some private fields and adding other ones. A key reason why you don't want to have private members accessible is because you might break some internal invariant. With parameters, there is no such concern, because they need to be accessible by definition, they are part of the interface. Your subsystems _need_ to be coupled at interfaces, you just want the interfaces to be small. More automated checking for consistency at interfaces is actually good. Checking for consistency of parameter and argument names might occasionally break compilation of code in superficial ways that are easily dealt with by changing the characters in some identifier, but it does not actually lead to the disadvantages you get with a poorly encapsulated system. Also consider that a library author can always note in the documentation that parameter names are not guaranteed to be stable, and that hence it is on the user of the library to trade off better type checking against fewer compilation errors when updating the library. Note that a compilation failure is actually the best kind of failure you can get when updating library versions.
Jun 07
prev sibling next sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler 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

 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.
There's a big issue with this DIP. It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it. I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e. add(int x, int y) // parameter names not helpful square(float x) // parameter names not helpful write(string s) // parameter names not helpful void opEquals(T)(ref T other) // parameter names not helpful Of course there are many cases where named arguments are very helpful (the DIP provides some examples of this). However, if you suddenly allow every caller to specify the argument names to any parameter on any function, you've added a whole new set of dependencies between every function and its callers. A layer of protection/encapsulation has been completely removed. It would be like if we suddenly disabled the "private" modifier and allowed everything to access private fields within structs and classes. Languages like python that uses kwargs don't expose the names of all parameters. They are able to pick and choose which parameters should be named. This allows them to keep that layer of protection/encapsulation for the parameters where the name doesn't matter to the caller, just like when you have private fields where the name doesn't matter to an outside component. D should follow this pattern as it has been successful in other languages and the alternative has too much disadvantage. Allowing a parameter to be named at the call-site should be an "opt-in" feature done at the function definition, so as not to expose the names of all the other parameters that don't make sense to expose to the caller.
Where were you during the last community review? :) Last time literally _everyone_ is arguing against named parameters being opt-in, and that's why I removed the opt-in-ness (the named attribute) from the DIP.
 It would be like if we suddenly disabled the "private" modifier 
 and allowed everything to access private fields within structs 
 and classes.
I don't think this is a fair comparison.
Jun 07
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 7 June 2019 at 12:09:51 UTC, Yuxuan Shui wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler 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

 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.
There's a big issue with this DIP. It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it. I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e. add(int x, int y) // parameter names not helpful square(float x) // parameter names not helpful write(string s) // parameter names not helpful void opEquals(T)(ref T other) // parameter names not helpful Of course there are many cases where named arguments are very helpful (the DIP provides some examples of this). However, if you suddenly allow every caller to specify the argument names to any parameter on any function, you've added a whole new set of dependencies between every function and its callers. A layer of protection/encapsulation has been completely removed. It would be like if we suddenly disabled the "private" modifier and allowed everything to access private fields within structs and classes. Languages like python that uses kwargs don't expose the names of all parameters. They are able to pick and choose which parameters should be named. This allows them to keep that layer of protection/encapsulation for the parameters where the name doesn't matter to the caller, just like when you have private fields where the name doesn't matter to an outside component. D should follow this pattern as it has been successful in other languages and the alternative has too much disadvantage. Allowing a parameter to be named at the call-site should be an "opt-in" feature done at the function definition, so as not to expose the names of all the other parameters that don't make sense to expose to the caller.
Where were you during the last community review? :) Last time literally _everyone_ is arguing against named parameters being opt-in, and that's why I removed the opt-in-ness (the named attribute) from the DIP.
I'm not actually sure if they should be opt-in. I'm pointing out the problem with them always being on. They way I suggested for them to be opt-in has 2 problems. One is that libraries will need to break compatibility with older compilers to enable them. Without opt-in, only the caller needs to do this. The second is that it users will have to wait for libraries to update before they can use the feature, and libraries may be hesitant to update to remain compatible with older compilers, at least for a while. I'm just pointing out a problem I see. We should all be aware of the problem. Whether or not the problem is a big deal or had a good solution is another question. I think it's a big deal, and we should solve it if we can.
 It would be like if we suddenly disabled the "private" 
 modifier and allowed everything to access private fields 
 within structs and classes.
I don't think this is a fair comparison.
Its not a perfect comparison. Getting rid of private on all fields would be much worse than only exposing parameter names. I would say it's a more mild version of removing private semantics.
Jun 07
parent reply Gregor =?UTF-8?B?TcO8Y2ts?= <gregormueckl gmx.de> writes:
On Friday, 7 June 2019 at 15:15:40 UTC, Jonathan Marler wrote:
 On Friday, 7 June 2019 at 12:09:51 UTC, Yuxuan Shui wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler 
 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

 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.
There's a big issue with this DIP. It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it. I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e. add(int x, int y) // parameter names not helpful square(float x) // parameter names not helpful write(string s) // parameter names not helpful void opEquals(T)(ref T other) // parameter names not helpful Of course there are many cases where named arguments are very helpful (the DIP provides some examples of this). However, if you suddenly allow every caller to specify the argument names to any parameter on any function, you've added a whole new set of dependencies between every function and its callers. A layer of protection/encapsulation has been completely removed. It would be like if we suddenly disabled the "private" modifier and allowed everything to access private fields within structs and classes. Languages like python that uses kwargs don't expose the names of all parameters. They are able to pick and choose which parameters should be named. This allows them to keep that layer of protection/encapsulation for the parameters where the name doesn't matter to the caller, just like when you have private fields where the name doesn't matter to an outside component. D should follow this pattern as it has been successful in other languages and the alternative has too much disadvantage. Allowing a parameter to be named at the call-site should be an "opt-in" feature done at the function definition, so as not to expose the names of all the other parameters that don't make sense to expose to the caller.
Where were you during the last community review? :) Last time literally _everyone_ is arguing against named parameters being opt-in, and that's why I removed the opt-in-ness (the named attribute) from the DIP.
I'm not actually sure if they should be opt-in. I'm pointing out the problem with them always being on. They way I suggested for them to be opt-in has 2 problems. One is that libraries will need to break compatibility with older compilers to enable them. Without opt-in, only the caller needs to do this. The second is that it users will have to wait for libraries to update before they can use the feature, and libraries may be hesitant to update to remain compatible with older compilers, at least for a while. I'm just pointing out a problem I see. We should all be aware of the problem. Whether or not the problem is a big deal or had a good solution is another question. I think it's a big deal, and we should solve it if we can.
C# has had named arguments for quite a while now without any way to opt in or opt out. If you want to name a function argument, you just do it. If it breaks, it breaks. I haven't seen breakage from that in practice, yet. Mostly, because people only use that syntax for complex functions that have long parameter lists or challenging parameter lists with 4 to 5 boolean parameters in row or something borderline insane like that. So, I'd say that it's in the ballpark of one in 1000 LoCs or less that actually use that language feature. Let's be real here: when is renaming a function argument the only change that happens to a function signature? If the argument's name and semantics change, the function's semantics change as well. This means that you need to review all your call sites anyway. And in my experience, even in large code bases, only a small section of the code is called from so many places that this is onerous. These are the same pieces of code that calcify into near-immutability anyway, because the slightest change is going to break something somewhere else, anyway. I'll just suggest a simple canary here: C# is a popular language and a lot has been written about it. How easy is it to find a statement that complains about the usage of named function arguments?
Jun 07
parent Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 7 June 2019 at 15:28:00 UTC, Gregor Mückl wrote:
 On Friday, 7 June 2019 at 15:15:40 UTC, Jonathan Marler wrote:
 On Friday, 7 June 2019 at 12:09:51 UTC, Yuxuan Shui wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler 
 wrote:
 [...]
Where were you during the last community review? :) Last time literally _everyone_ is arguing against named parameters being opt-in, and that's why I removed the opt-in-ness (the named attribute) from the DIP.
I'm not actually sure if they should be opt-in. I'm pointing out the problem with them always being on. They way I suggested for them to be opt-in has 2 problems. One is that libraries will need to break compatibility with older compilers to enable them. Without opt-in, only the caller needs to do this. The second is that it users will have to wait for libraries to update before they can use the feature, and libraries may be hesitant to update to remain compatible with older compilers, at least for a while. I'm just pointing out a problem I see. We should all be aware of the problem. Whether or not the problem is a big deal or had a good solution is another question. I think it's a big deal, and we should solve it if we can.
C# has had named arguments for quite a while now without any way to opt in or opt out. If you want to name a function argument, you just do it. If it breaks, it breaks. I haven't seen breakage from that in practice, yet. Mostly, because people only use that syntax for complex functions that have long parameter lists or challenging parameter lists with 4 to 5 boolean parameters in row or something borderline insane like that. So, I'd say that it's in the ballpark of one in 1000 LoCs or less that actually use that language feature.
Maybe I am over-estimating the problem with exposing parameter names. It was also pointed out that python actually does expose all it's parameter names, not just kwargs. If people only use parameter names in cases where they make sense, then I agree that this is a non-issue. By making it opt-in, you can guarantee that you're library won't be misused so you will still be free to change it without people complaining when you break their mis-use of your library. The less people mis-use the feature, the less of a problem it becomes. I'd be curious to see how named parameters has affected development decisions for libraries in C#. The Microsoft .NET Framework Libraries are pretty exhaustive, and once an API is in place, it usually never changes. They usually only *ADD* new APIs and rarely change existing ones. I wonder if they had any issues with legacy parameter names that weren't necessarily consistent once they enabled named parameters for everything. Something to look into.
Jun 07
prev sibling next sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
 On Wednesday, 5 June 2019 at 13:03:26 UTC, Mike Parker wrote:
 [...]
There's a big issue with this DIP. It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it. I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e. [...]
See also: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4172.htm The answer to objection #3 addresses your concern.
Jun 07
parent Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 7 June 2019 at 14:13:42 UTC, Yuxuan Shui wrote:
 On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
 On Wednesday, 5 June 2019 at 13:03:26 UTC, Mike Parker wrote:
 [...]
There's a big issue with this DIP. It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it. I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e. [...]
See also: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4172.htm The answer to objection #3 addresses your concern.
A good idea to get data like this. But I think what will happen if/when we enable named arguments is that there will be a spike in the number of changes to parameter names. The idea being that now that they are apart of the interface, we will want to normalize names for things like opCmp, opEquals, copy functions, one value operation functions, etc. square(x: 10); cube(num: 10); quad(val: 10); These would be examples of functions that don't benefit from named arguments, but because we've exposed the parameter names of every function, we've add a new burden to maintain/normalize these names for no benefit. At least, no benefit for these particular functions. If we make it "opt-in", we only need to be concerned with functions that make their parameter names public, and when we make them public, we can normalize the parameter names at the same time knowing that we aren't breaking anything.
Jun 07
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
 Languages like python that uses kwargs don't expose the names 
 of all parameters.  They are able to pick and choose which 
 parameters should be named.  This allows them to keep that 
 layer of protection/encapsulation for the parameters where the 
 name doesn't matter to the caller, just like when you have 
 private fields where the name doesn't matter to an outside 
 component.
Point of fact: python allows any parameter to be passed by name, not just kwargs: def f(x, y): return x - y print(f(y=2, x=5)) # prints "3" The only languages I'm aware of with named arguments that require parameters to be explicitly marked as named in the function definition are Common Lisp [1] and Scheme [2]. In these languages, named parameters are entirely distinct from positional parameters--named parameters may only be passed by name, and positional parameters may only be passed by position. [1] https://ccrma.stanford.edu/courses/220b-winter-2005/topics/commonlisp/arguments.html [2] https://srfi.schemers.org/srfi-89/srfi-89.html
Jun 07
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
I'll reiterate what I wrote for DIP1020 
https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1_325299.html#N325627

---

Here's a much simpler proposal, based on the recognition that D already has
named parameters:

    https://dlang.org/spec/struct.html#static_struct_init

and related:

    https://dlang.org/spec/hash-map.html#static_initialization
    https://dlang.org/spec/arrays.html#static-init-static

The only additional syntax would be allowing the equivalent of
https://dlang.org/spec/hash-map.html#static_initialization in the argument
list.
Assignment of arguments to parameters would work the same way as assignments to
fields.

As for the semantics, given this constraint, nothing needs to be invented, just
discovered as necessary behavior. Consider:

     void snoopy(T t, int i, S s);     // A
     void snoopy(S s, int i = 0; T t); // B

and calling it:

     S s; T t; int i;
     snoopy(t, i, s); // A
     snoopy(s, i, t); // B
     snoopy(s, t); // error, neither A nor B match
     snoopy(t, s); // error, neither A nor B match
     snoopy(s:s, t:t, i:i); // error, ambiguous
     snoopy(s:s, t:t); // B
     snoopy(t:t, s:s); // B
     snoopy(t:t, i, s:s); // A
     snoopy(s:s, t:t, i); // A

I.e. function resolution is done by constructing an argument list separately
for
each function before testing it for matching. Of course, if the parameter
name(s) don't match, the function doesn't match. If a parameter has no
corresponding argument, and no default value, then the function doesn't match.

I don't see much point in requiring the names, preventing use of names, nor
aliasing them. This has never been an issue for struct initializers.

One nice thing about this is the { } struct initialization syntax can be
deprecated, as S(a:1, b:2) can replace it, and would be interchangeable with
constructor syntax, making for a nice unification. (Like was done for array
initialization.)

One issue would be order of evaluation: would the arguments be evaluated in the
lexical order of the arguments, or the lexical order of the parameters?

Rationale:

Although this supports reordering, the real reason for naming is so one can
have
a function with a longish list of parameters, each with a reasonable default,
and the user need only supply the arguments that matter for his use case. This
is much more flexible than the current method of putting all the defaults at
the
end of the parameter list, and defaulting one means all the rest get defaulted.

A secondary reason is (again) for a longish list of parameters, when the user
finds himself counting parameters to ensure they line up, then named parameters
can be most helpful.
Jun 06
next sibling parent reply Aliak <something something.com> writes:
On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
    discovered as necessary behavior. Consider:

     void snoopy(T t, int i, S s);     // A
     void snoopy(S s, int i = 0; T t); // B

 and calling it:

     S s; T t; int i;
     snoopy(t, i, s); // A
     snoopy(s, i, t); // B
     snoopy(s, t); // error, neither A nor B match
     snoopy(t, s); // error, neither A nor B match
     snoopy(s:s, t:t, i:i); // error, ambiguous
     snoopy(s:s, t:t); // B
     snoopy(t:t, s:s); // B
     snoopy(t:t, i, s:s); // A
     snoopy(s:s, t:t, i); // A
Trying to understand why the last two call A and are not ambiguous?
 One issue would be order of evaluation: would the arguments be 
 evaluated in the
 lexical order of the arguments, or the lexical order of the 
 parameters?
Arguments would provide consistency but parameters feel more intuitive from a user perspective. But yeah, hard to say!
Jun 06
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/6/2019 2:43 PM, Aliak wrote:
 On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
    discovered as necessary behavior. Consider:

     void snoopy(T t, int i, S s);     // A
     void snoopy(S s, int i = 0; T t); // B

 and calling it:

     snoopy(t:t, i, s:s); // A
     snoopy(s:s, t:t, i); // A
Trying to understand why the last two call A and are not ambiguous?
Argument `i` is not named, and so can only appear after `t` in A, and only after `s` in B. This only works for A.
Jun 06
parent reply aliak <something something.com> writes:
On Friday, 7 June 2019 at 06:30:15 UTC, Walter Bright wrote:
 On 6/6/2019 2:43 PM, Aliak wrote:
 On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
    discovered as necessary behavior. Consider:

     void snoopy(T t, int i, S s);     // A
     void snoopy(S s, int i = 0; T t); // B

 and calling it:

     snoopy(t:t, i, s:s); // A
     snoopy(s:s, t:t, i); // A
Trying to understand why the last two call A and are not ambiguous?
Argument `i` is not named, and so can only appear after `t` in A, and only after `s` in B. This only works for A.
What makes i unnamed and the others named? You mean you want for unnamed arguments to only occur after the last named argument?
Jun 07
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/7/2019 1:07 AM, aliak wrote:
 What makes i unnamed and the others named?
snoopy(t:t, i, s:s); ^ note this is not i:i
Jun 07
parent aliak <something something.com> writes:
On Friday, 7 June 2019 at 09:23:42 UTC, Walter Bright wrote:
 On 6/7/2019 1:07 AM, aliak wrote:
 What makes i unnamed and the others named?
snoopy(t:t, i, s:s); ^ note this is not i:i
Ah! The way it's called of course. I'm so used to working with swift that i forget that it can *also* be controlled client side :)
Jun 07
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 06.06.19 22:04, Walter Bright wrote:
 I'll reiterate what I wrote for DIP1020 
 https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1
325299.html#N325627 
 
 
 ---
 
 Here's a much simpler proposal, based on the recognition that D already has
 named parameters:
 ...
I think this is indeed the way to go, but ideally, named arguments would become first-class citizens. E.g., this should work: [1] void foo(int x,string y){} void main(){ auto t=tuple(y: "123", x: 2); foo(t.expand); // ok } I.e., named arguments should be allowed in alias sequences. This is important e.g. for forwarding applications. [1] With the tuple DIP, it would become just void main(){ auto t=(y: "123", x: 2); foo(t); }
Jun 06
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 06.06.19 22:04, Walter Bright wrote:
 
 
 One issue would be order of evaluation: would the arguments be evaluated 
 in the
 lexical order of the arguments, or the lexical order of the parameters?
Lexical order of the arguments. Evaluating in order of source code is a good policy. Also, this is the only sensible choice considering that named alias sequences should be an independent concept.
Jun 06
prev sibling next sibling parent Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
 Although this supports reordering, the real reason for naming 
 is so one can
 have
 a function with a longish list of parameters, each with a 
 reasonable default,
 and the user need only supply the arguments that matter for his 
 use case. This
 is much more flexible than the current method of putting all 
 the defaults at
 the
 end of the parameter list, and defaulting one means all the 
 rest get defaulted.

 A secondary reason is (again) for a longish list of parameters, 
 when the user
 finds himself counting parameters to ensure they line up, then 
 named parameters
 can be most helpful.
It's also useful for 1. boolean flags foo(true); foo(log: true); 2. parameters with units sleep(1); sleep(seconds: 1); 3. parameters where the order matters but is not obvious copy(a, b); copy(src: a, dst: b); Of course there are other ways to accomplish these such as using abstract types like Flag and Duration to specify names and units or establishing name conventions to indicate parameter ordering. But named parameters also make these cases pretty convenient.
Jun 06
prev sibling next sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
 I'll reiterate what I wrote for DIP1020 
 https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1_325299.html#N325627

 ---

 Here's a much simpler proposal, based on the recognition that D 
 already has
 named parameters:

    https://dlang.org/spec/struct.html#static_struct_init

 and related:

    https://dlang.org/spec/hash-map.html#static_initialization
    https://dlang.org/spec/arrays.html#static-init-static

 The only additional syntax would be allowing the equivalent of
 https://dlang.org/spec/hash-map.html#static_initialization in 
 the argument
 list.
 Assignment of arguments to parameters would work the same way 
 as assignments to
 fields.

 As for the semantics, given this constraint, nothing needs to 
 be invented, just
 discovered as necessary behavior. Consider:

     void snoopy(T t, int i, S s);     // A
     void snoopy(S s, int i = 0; T t); // B

 and calling it:

     S s; T t; int i;
     snoopy(t, i, s); // A
     snoopy(s, i, t); // B
     snoopy(s, t); // error, neither A nor B match
     snoopy(t, s); // error, neither A nor B match
     snoopy(s:s, t:t, i:i); // error, ambiguous
     snoopy(s:s, t:t); // B
     snoopy(t:t, s:s); // B
     snoopy(t:t, i, s:s); // A
     snoopy(s:s, t:t, i); // A

 I.e. function resolution is done by constructing an argument 
 list separately
 for
 each function before testing it for matching. Of course, if the 
 parameter
 name(s) don't match, the function doesn't match. If a parameter 
 has no
 corresponding argument, and no default value, then the function 
 doesn't match.

 I don't see much point in requiring the names, preventing use 
 of names, nor
 aliasing them. This has never been an issue for struct 
 initializers.

 One nice thing about this is the { } struct initialization 
 syntax can be
 deprecated, as S(a:1, b:2) can replace it, and would be 
 interchangeable with
 constructor syntax, making for a nice unification. (Like was 
 done for array
 initialization.)

 One issue would be order of evaluation: would the arguments be 
 evaluated in the
 lexical order of the arguments, or the lexical order of the 
 parameters?

 Rationale:

 Although this supports reordering, the real reason for naming 
 is so one can
 have
 a function with a longish list of parameters, each with a 
 reasonable default,
 and the user need only supply the arguments that matter for his 
 use case. This
 is much more flexible than the current method of putting all 
 the defaults at
 the
 end of the parameter list, and defaulting one means all the 
 rest get defaulted.

 A secondary reason is (again) for a longish list of parameters, 
 when the user
 finds himself counting parameters to ensure they line up, then 
 named parameters
 can be most helpful.
I don't necessarily see any problems with this proposal. (Also, I think this is a superset of my DIP). But I don't think what you have written here covers all of the nitty-gritty that could arise if your proposal is implemented. I don't have a really strong example off the top of head, but I have a couple of small things that need clarification: 1. (Clearly function overloading is affected, but) is name mangling also affected? 2. What about declarations in .di files? 3. What about function declarations with parameter names different from the definition?
 I don't see much point in requiring the names, preventing use 
 of names, nor
 aliasing them. This has never been an issue for struct 
 initializers.
There is at least on difference here: structs can have private members.
Jun 07
parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/7/2019 5:27 AM, Yuxuan Shui wrote:
 1. (Clearly function overloading is affected, but) is name mangling also
affected?
No.
 2. What about declarations in .di files?
No.
 3. What about function declarations with parameter names different from the 
 definition?
The declaration the compiler sees is what matters.
Jun 07
prev sibling next sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
 I'll reiterate what I wrote for DIP1020 
 https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1_325299.html#N325627
And how do you deal with: void func(Args...)(Args args); ?
Jun 07
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/7/2019 6:27 AM, Yuxuan Shui wrote:
 And how do you deal with:
 
      void func(Args...)(Args args);
 
 ?
It doesn't make sense to use named parameters for arbitrary arguments of arbitrary types.
Jun 07
prev sibling parent Kagamin <spam here.lot> writes:
On Friday, 7 June 2019 at 13:27:12 UTC, Yuxuan Shui wrote:
 On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
 I'll reiterate what I wrote for DIP1020 
 https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1_325299.html#N325627
And how do you deal with: void func(Args...)(Args args); ?
Something like func(args:(1,2,3)); `Name: TupleLiteral`
Jun 08
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2019-06-06 22:04, Walter Bright wrote:
 I'll reiterate what I wrote for DIP1020 
 https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1
325299.html#N325627 
 
 
 ---
 
 Here's a much simpler proposal, based on the recognition that D already has
 named parameters:
 
     https://dlang.org/spec/struct.html#static_struct_init
 
 and related:
 
     https://dlang.org/spec/hash-map.html#static_initialization
     https://dlang.org/spec/arrays.html#static-init-static
 
 The only additional syntax would be allowing the equivalent of
 https://dlang.org/spec/hash-map.html#static_initialization in the argument
 list.
 Assignment of arguments to parameters would work the same way as 
 assignments to
 fields.
Related https://github.com/dlang/DIPs/pull/71.
 As for the semantics, given this constraint, nothing needs to be 
 invented, just
 discovered as necessary behavior. Consider:
 
      void snoopy(T t, int i, S s);     // A
      void snoopy(S s, int i = 0; T t); // B
 
 and calling it:
 
      S s; T t; int i;
      snoopy(t, i, s); // A
      snoopy(s, i, t); // B
      snoopy(s, t); // error, neither A nor B match
      snoopy(t, s); // error, neither A nor B match
      snoopy(s:s, t:t, i:i); // error, ambiguous
      snoopy(s:s, t:t); // B
      snoopy(t:t, s:s); // B
      snoopy(t:t, i, s:s); // A
      snoopy(s:s, t:t, i); // A
 
 I.e. function resolution is done by constructing an argument list 
 separately
 for
 each function before testing it for matching. Of course, if the parameter
 name(s) don't match, the function doesn't match. If a parameter has no
 corresponding argument, and no default value, then the function doesn't 
 match.
 
 I don't see much point in requiring the names, preventing use of names, nor
 aliasing them. This has never been an issue for struct initializers.
 
 One nice thing about this is the { } struct initialization syntax can be
 deprecated, as S(a:1, b:2) can replace it, and would be interchangeable 
 with
 constructor syntax, making for a nice unification. (Like was done for array
 initialization.)
 
 One issue would be order of evaluation: would the arguments be evaluated 
 in the
 lexical order of the arguments, or the lexical order of the parameters?
 
 Rationale:
 
 Although this supports reordering, the real reason for naming is so one can
 have
 a function with a longish list of parameters, each with a reasonable 
 default,
 and the user need only supply the arguments that matter for his use 
 case. This
 is much more flexible than the current method of putting all the 
 defaults at
 the
 end of the parameter list, and defaulting one means all the rest get 
 defaulted.
 
 A secondary reason is (again) for a longish list of parameters, when the 
 user
 finds himself counting parameters to ensure they line up, then named 
 parameters
 can be most helpful.
This is similar to how it works in Ruby: foo({ "asd" => 3 }) # pass a hash (associative array) to "foo" It's also common to pass a symbol instead of a string when the valid keys are few: foo({ :asd => 3 }) In a function call, when passing a hash, it's possible to drop the curly braces: foo(:asd => 3) In Ruby 1.9 they added syntax sugar constructing hashes with symbols as the keys: foo({ asd: 3 }) Combining that with the possibility to drop the curly braces you basically get named arguments: foo(asd: 3) Note that in all these cases the hash corresponds to one parameter at the declaration site. Then in Ruby 2.0, proper named arguments were added. This requires opt-in on the declaration site: def foo(bar:, asd: 3) end Using the colon (:) on the declaration site requires the caller to supply the named arguments. foo(1, 2) # error foo(bar: 1, asd: 2) # ok -- /Jacob Carlborg
Jun 07
prev sibling next sibling parent Atila Neves <atila.neves gmail.com> writes:
On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
 I'll reiterate what I wrote for DIP1020 
 https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1_325299.html#N325627

 ---
 <snip>
 One nice thing about this is the { } struct initialization 
 syntax can be
 deprecated, as S(a:1, b:2) can replace it, and would be 
 interchangeable with
 constructor syntax, making for a nice unification. (Like was 
 done for array
 initialization.)
This, plus what Timon added, seems to be a far superior alternative. I like it.
Jun 08
prev sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
 I'll reiterate what I wrote for DIP1020 
 https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1_325299.html#N325627

 ---

 Here's a much simpler proposal, based on the recognition that D 
 already has
 named parameters:

    https://dlang.org/spec/struct.html#static_struct_init

 and related:

    https://dlang.org/spec/hash-map.html#static_initialization
    https://dlang.org/spec/arrays.html#static-init-static

 The only additional syntax would be allowing the equivalent of
 https://dlang.org/spec/hash-map.html#static_initialization in 
 the argument
 list.
 Assignment of arguments to parameters would work the same way 
 as assignments to
 fields.

 As for the semantics, given this constraint, nothing needs to 
 be invented, just
 discovered as necessary behavior. Consider:

     void snoopy(T t, int i, S s);     // A
     void snoopy(S s, int i = 0; T t); // B

 and calling it:

     S s; T t; int i;
     snoopy(t, i, s); // A
     snoopy(s, i, t); // B
     snoopy(s, t); // error, neither A nor B match
     snoopy(t, s); // error, neither A nor B match
     snoopy(s:s, t:t, i:i); // error, ambiguous
     snoopy(s:s, t:t); // B
     snoopy(t:t, s:s); // B
Unlike the other cases, this one seems particularly surprising.
     snoopy(t:t, i, s:s); // A
     snoopy(s:s, t:t, i); // A
This is another re-ordering case, which makes my brain have to strain for a second.
 I.e. function resolution is done by constructing an argument 
 list separately
 for
 each function before testing it for matching. Of course, if the 
 parameter
 name(s) don't match, the function doesn't match. If a parameter 
 has no
 corresponding argument, and no default value, then the function 
 doesn't match.

 I don't see much point in requiring the names, preventing use 
 of names, nor
 aliasing them. This has never been an issue for struct 
 initializers.

 One nice thing about this is the { } struct initialization 
 syntax can be
 deprecated, as S(a:1, b:2) can replace it, and would be 
 interchangeable with
 constructor syntax, making for a nice unification. (Like was 
 done for array
 initialization.)

 One issue would be order of evaluation: would the arguments be 
 evaluated in the
 lexical order of the arguments, or the lexical order of the 
 parameters?

 Rationale:

 Although this supports reordering, the real reason for naming 
 is so one can
 have
 a function with a longish list of parameters, each with a 
 reasonable default,
 and the user need only supply the arguments that matter for his 
 use case. This
 is much more flexible than the current method of putting all 
 the defaults at
 the
 end of the parameter list, and defaulting one means all the 
 rest get defaulted.

 A secondary reason is (again) for a longish list of parameters, 
 when the user
 finds himself counting parameters to ensure they line up, then 
 named parameters
 can be most helpful.
I see value in allowing a caller to omit arguments that have default values, but what is the value in allowing the caller to reorder them? Allowing re-ordering seems to cause surprising results, such as the ones I noted above, and also causes a new decision to made, namely, which order should arguments be evaluated in (which you noted). It also means that in order to understand what overload you are calling, you need to check EVERY argument before you can determine this. If you don't allow re-ordering, you can rule out overloads sooner as you only need to check whether the next named argument matches the next named parameter. To demonstrate, in the above example, if I saw
     snoopy(t:t,...
I can immediately rule out overload B since parameter `s` must always come before `t`. I don't have to check the rest of the arguments to see if there is a "s: ...", and then make sure to remember that it does as I move through the rest of the parameters. The amount of memory a human will need to track while evaluating which overload is taken as the number of parameters grows will be unmanageable if re-ordering is allowed. And, usually the most useful cases for this are the ones where there are alot of parameters.
Jun 08
next sibling parent Jonathan Marler <johnnymarler gmail.com> writes:
On Saturday, 8 June 2019 at 18:05:43 UTC, Jonathan Marler wrote:
 On Thursday, 6 June 2019 at 20:04:15 UTC, Walter Bright wrote:
     [...]
Unlike the other cases, this one seems particularly surprising.
     [...]
This is another re-ordering case, which makes my brain have to strain for a second.
 [...]
I see value in allowing a caller to omit arguments that have default values, but what is the value in allowing the caller to reorder them? Allowing re-ordering seems to cause surprising results, such as the ones I noted above, and also causes a new decision to made, namely, which order should arguments be evaluated in (which you noted). It also means that in order to understand what overload you are calling, you need to check EVERY argument before you can determine this. If you don't allow re-ordering, you can rule out overloads sooner as you only need to check whether the next named argument matches the next named parameter. To demonstrate, in the above example, if I saw
     [...]
I can immediately rule out overload B since parameter `s` must always come before `t`. I don't have to check the rest of the arguments to see if there is a "s: ...", and then make sure to remember that it does as I move through the rest of the parameters. The amount of memory a human will need to track while evaluating which overload is taken as the number of parameters grows will be unmanageable if re-ordering is allowed. And, usually the most useful cases for this are the ones where there are alot of parameters.
By the way, I think your proposal is basically DIP 1019 except allowing default arguments to be skipped and allowing re-ordering. But again, I maintain that re-ordering seems to be add more confusion than it does value. Reordering isn't a problem with struct initialization as there's no such thing as struct initialization overloading :)
Jun 08
prev sibling next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 8 June 2019 at 18:05:43 UTC, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that have 
 default values, but what is the value in allowing the caller to 
 reorder them?
Without looking at the documentation, which of the following calls would fail to compile if argument reordering was forbidden? spawnProcess("/usr/bin/sort", stdout: outputFile, stdin: inputFile); spawnProcess("/usr/bin/sort", stdin: inputFile, stdout: outputFile); From a usability perspective, it's completely insane for only one of these to work.
Jun 08
next sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Sunday, 9 June 2019 at 01:34:50 UTC, Paul Backus wrote:
 On Saturday, 8 June 2019 at 18:05:43 UTC, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that have 
 default values, but what is the value in allowing the caller 
 to reorder them?
Without looking at the documentation, which of the following calls would fail to compile if argument reordering was forbidden? spawnProcess("/usr/bin/sort", stdout: outputFile, stdin: inputFile); spawnProcess("/usr/bin/sort", stdin: inputFile, stdout: outputFile); From a usability perspective, it's completely insane for only one of these to work.
Of the top of my head stdin is first...but I don't think many people would know that. It's just that I've written wrappers to spawnProcess so many times that it's ingrained in my head. But I think whether or not I know is irrelevent to your point :) I believe that optimizing code for the reader should take priority over optimizing for the writer. The antithetical example is the perl language...writing it can be terse and quick but reading it can make your head spin. I think your point is that when developers write code like this, having to put arguments in a particular order seems like an unnecessary burden. I agree it's an extra burden on the writer, but enforcing the same order reduces the complexity of overload resolution and knowing how to map arguments to parameters, something which the "reader" needs to be able to do whenever they see a function call. Consider, foo(int a, int b, int c, int d, int e, int f); foo(1, 2, 3, 4, 5, 6); // a=1, b=2, c=3, d=4, e=5, f=6 Now let's see it with some argument re-ordering: foo(6, c=1, e=2, 3, b=4, e=5, a=7); What's the values of a/b/c/d/e/f in this case? This may have made sense when it was written, but this is not beneficial for the reader. This gets worse when you introduce the concept of order-of-evaluation: int x = 0; foo(x++, c=x++, e=x++, x++, b=x++, e=x++, a=x++); Now what are the values of a/b/c/d/e/f? Do you evaluate arguments in the order of the call, or the order of the function definition? These are the problems before you get into overloading. Now add that into the mix: foo(float a, float b, float c, int d, float e, float f); foo(float a, float b, float c, float d, float e, int f); foo(0, c=1, 2.0, 0.0, b=4, e=5, a=7); ... Keep in mind that I'm not saying that by enabling re-ordering we're going to start having a huge mass of unreadable code like this. These examples are contrived to show you how re-ordering can make things confusing. But when you enable powerful things like this, you are adding an extra burden on the reader every time they see a function call. The more rules you add, the more unsure you make the reader and the more rules the reader has to remember and evaluate in order to understand the code. Now whenever they see a function call with named arguments, they're going to have to go through a mental checklist of rules to be sure which overload is actually being called and which parameters are receiving which arguments. The benefit of allowing the writer to re-order arguments should be weighed against the burden of the reader to then understand it later when they do.
Jun 08
next sibling parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Sunday, 9 June 2019 at 02:49:13 UTC, Jonathan Marler wrote:
 I think your point is that when developers write code like 
 this, having to put arguments in a particular order seems like 
 an unnecessary burden.  I agree it's an extra burden on the 
 writer, but enforcing the same order reduces the complexity of 
 overload resolution and knowing how to map arguments to 
 parameters, something which the "reader" needs to be able to do 
 whenever they see a function call.

 Consider,

 foo(int a, int b, int c, int d, int e, int f);

 foo(1, 2, 3, 4, 5, 6); // a=1, b=2, c=3, d=4, e=5, f=6

 Now let's see it with some argument re-ordering:

 foo(6, c=1, e=2, 3, b=4, e=5, a=7);
overload error, you have 7 parameters here but only 6 in the definition and no 7 parameter overload.
 What's the values of a/b/c/d/e/f in this case? This may have 
 made sense when it was written, but this is not beneficial for 
 the reader.
none, it's a compilation error
Jun 09
prev sibling next sibling parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Sunday, 9 June 2019 at 02:49:13 UTC, Jonathan Marler wrote:
 This gets worse when you introduce the concept of 
 order-of-evaluation:

 int x = 0;
 foo(x++, c=x++, e=x++, x++, b=x++, e=x++, a=x++);

 Now what are the values of a/b/c/d/e/f?  Do you evaluate 
 arguments in the order of the call, or the order of the 
 function definition?
They are in the order of declaration of the function. But here again you have 7 parameter for a function who takes only 6. But they will have a=1 b=2 c=3 (d=4) There's no reason to evaluate it any other order as the code generation requires that the caller populates the registers/stack in the order the function expects.
Jun 09
prev sibling next sibling parent reply Piotr Duda <duda.piotr gmail.com> writes:
niedz., 9 cze 2019 o 04:50 Jonathan Marler via Digitalmars-d
<digitalmars-d puremagic.com> napisał(a):
 On Sunday, 9 June 2019 at 01:34:50 UTC, Paul Backus wrote:
 On Saturday, 8 June 2019 at 18:05:43 UTC, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that have
 default values, but what is the value in allowing the caller
 to reorder them?
Without looking at the documentation, which of the following calls would fail to compile if argument reordering was forbidden? spawnProcess("/usr/bin/sort", stdout: outputFile, stdin: inputFile); spawnProcess("/usr/bin/sort", stdin: inputFile, stdout: outputFile); From a usability perspective, it's completely insane for only one of these to work.
Of the top of my head stdin is first...but I don't think many people would know that. It's just that I've written wrappers to spawnProcess so many times that it's ingrained in my head. But I think whether or not I know is irrelevent to your point :) I believe that optimizing code for the reader should take priority over optimizing for the writer. The antithetical example is the perl language...writing it can be terse and quick but reading it can make your head spin. I think your point is that when developers write code like this, having to put arguments in a particular order seems like an unnecessary burden. I agree it's an extra burden on the writer, but enforcing the same order reduces the complexity of overload resolution and knowing how to map arguments to parameters, something which the "reader" needs to be able to do whenever they see a function call. Consider, foo(int a, int b, int c, int d, int e, int f); foo(1, 2, 3, 4, 5, 6); // a=1, b=2, c=3, d=4, e=5, f=6 Now let's see it with some argument re-ordering: foo(6, c=1, e=2, 3, b=4, e=5, a=7); What's the values of a/b/c/d/e/f in this case? This may have made sense when it was written, but this is not beneficial for the reader. This gets worse when you introduce the concept of order-of-evaluation: int x = 0; foo(x++, c=x++, e=x++, x++, b=x++, e=x++, a=x++); Now what are the values of a/b/c/d/e/f? Do you evaluate arguments in the order of the call, or the order of the function definition? These are the problems before you get into overloading. Now add that into the mix: foo(float a, float b, float c, int d, float e, float f); foo(float a, float b, float c, float d, float e, int f); foo(0, c=1, 2.0, 0.0, b=4, e=5, a=7); ... Keep in mind that I'm not saying that by enabling re-ordering we're going to start having a huge mass of unreadable code like this. These examples are contrived to show you how re-ordering can make things confusing. But when you enable powerful things like this, you are adding an extra burden on the reader every time they see a function call. The more rules you add, the more unsure you make the reader and the more rules the reader has to remember and evaluate in order to understand the code. Now whenever they see a function call with named arguments, they're going to have to go through a mental checklist of rules to be sure which overload is actually being called and which parameters are receiving which arguments. The benefit of allowing the writer to re-order arguments should be weighed against the burden of the reader to then understand it later when they do.
There is simple solution for this, don't allow positional arguments after named.
Jun 09
parent Jonathan Marler <johnnymarler gmail.com> writes:
On Sunday, 9 June 2019 at 08:20:15 UTC, Piotr Duda wrote:
 niedz., 9 cze 2019 o 04:50 Jonathan Marler via Digitalmars-d 
 <digitalmars-d puremagic.com> napisał(a):
 [...]
There is simple solution for this, don't allow positional arguments after named.
Yeah that seems to solve most if not all of the issues I pointed out.
Jun 09
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Sunday, 9 June 2019 at 02:49:13 UTC, Jonathan Marler wrote:
 I believe that optimizing code for the reader should take 
 priority over optimizing for the writer.  The antithetical 
 example is the perl language...writing it can be terse and 
 quick but reading it can make your head spin.
I agree, but forcing the programmer to put stdin before stdout is optimizing for neither the reader nor the writer; it's optimizing for the compiler developer. Both calls to spawnProcess are equally easy to read and write.
 Consider,

 foo(int a, int b, int c, int d, int e, int f);

 foo(1, 2, 3, 4, 5, 6); // a=1, b=2, c=3, d=4, e=5, f=6

 Now let's see it with some argument re-ordering:

 foo(6, c=1, e=2, 3, b=4, e=5, a=7);

 What's the values of a/b/c/d/e/f in this case? This may have 
 made sense when it was written, but this is not beneficial for 
 the reader.
In this case, you get a compile error, because you've passed seven arguments to a six-parameter function, and some of them are duplicates. :) That aside, I think this example is only convincing because you've gone out of your way to choose parameter names and arguments that have an obvious order to them. Here's what happens if I replace them with names and values that don't follow any particular sequence: // Declaration double foo(double x, double t, double delta, double phi, double m, double tau); // Call without names foo(-65.22, 0.0783, 943.8, -1.7847, -7982.0, 0.8341); // Call with names and no reordering foo(-65.22, t=0.0783, delta=943.8, phi=-1.7847, m=-7892.0, 0.8341); // Call with names and reordering foo(-65.22, delta=943.8, m=-7892.0, 0.8341, t=0.0783, phi=-1.7847); To my eyes, the second and third calls look equally readable. In both cases, you can read off the values of four of the parameters from the names, you know that -65.22 is the value of the first parameter, and you know that 0.8341 is the value of the parameter that comes after `m`. In both cases, you'll have to look at the function signature to find out what the two unnamed parameters mean, unless you've memorized that `x` comes before `tau`. Of course, the *most* readable way to call this function would be to use names for every argument--and then it wouldn't matter at all what order they were in.
 This gets worse when you introduce the concept of 
 order-of-evaluation:

 int x = 0;
 foo(x++, c=x++, e=x++, x++, b=x++, e=x++, a=x++);

 Now what are the values of a/b/c/d/e/f?  Do you evaluate 
 arguments in the order of the call, or the order of the 
 function definition?
Personally, I think the obviously-correct choice is to evaluate them in lexical order (i.e., order of the call). Either way, though, this is something people will have to look up in the language spec the first time they see it, so it does make the language a little more difficult to learn. Of course, for this specific example, the real answer is "don't write code like that."
 These are the problems before you get into overloading.  Now 
 add that into the mix:

 foo(float a, float b, float c, int   d, float e, float f);
 foo(float a, float b, float c, float d, float e, int f);

 foo(0, c=1, 2.0, 0.0, b=4, e=5, a=7);

 ...

 [...] Now whenever they see a function call with named 
 arguments, they're going to have to go through a mental 
 checklist of rules to be sure which overload is actually being 
 called and which parameters are receiving which arguments.
I think if you write overload sets like this, someone reading your code is going to have a bad time regardless of whether you use reordering or not. Compare: foo(0, c=1, 2.0, 0.0, b=4, f=5); // with reordering foo(0, b=4, c=1, 2.0, 0.0, f=5); // without reordering In both cases, you have to find `d` and `f` in the argument list to figure out which overload is called. In both calls, `f` is named, so it's easy to find, and `d` is passed positionally, so you have to find it by looking for `c` and counting one argument to the right. Of course, an even more readable way to call this function would be to pass both `d` and `f` as named arguments--and if you did that, the order you passed them in wouldn't matter. All in all, the conclusion I draw from this discussion is that allowing argument reordering makes good code easier to write without harming readability, at the expense of potentially making bad code less readable. That seems to me like an acceptable tradeoff, especially since programmers are unlikely in practice to use named arguments in ways that don't improve the readability of their code.
Jun 09
prev sibling parent reply aliak <something something.com> writes:
On Sunday, 9 June 2019 at 01:34:50 UTC, Paul Backus wrote:
 On Saturday, 8 June 2019 at 18:05:43 UTC, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that have 
 default values, but what is the value in allowing the caller 
 to reorder them?
Without looking at the documentation, which of the following calls would fail to compile if argument reordering was forbidden? spawnProcess("/usr/bin/sort", stdout: outputFile, stdin: inputFile); spawnProcess("/usr/bin/sort", stdin: inputFile, stdout: outputFile); From a usability perspective, it's completely insane for only one of these to work.
Without looking at the documentation, what are the parameters of this function blah(...) ?
Jun 09
parent reply Paul Backus <snarwin gmail.com> writes:
On Sunday, 9 June 2019 at 11:16:30 UTC, aliak wrote:
 On Sunday, 9 June 2019 at 01:34:50 UTC, Paul Backus wrote:
 Without looking at the documentation, which of the following 
 calls would fail to compile if argument reordering was 
 forbidden?

 spawnProcess("/usr/bin/sort", stdout: outputFile, stdin: 
 inputFile);
 spawnProcess("/usr/bin/sort", stdin: inputFile, stdout: 
 outputFile);

 From a usability perspective, it's completely insane for only 
 one of these to work.
Without looking at the documentation, what are the parameters of this function blah(...) ?
My point is not that programmers should be able to write code without ever looking at documentation, it's that programmers should not have to do mindless busywork that the compiler could just as easily do for them.
Jun 09
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Sunday, June 9, 2019 12:40:21 PM MDT Paul Backus via Digitalmars-d wrote:
 On Sunday, 9 June 2019 at 11:16:30 UTC, aliak wrote:
 On Sunday, 9 June 2019 at 01:34:50 UTC, Paul Backus wrote:
 Without looking at the documentation, which of the following
 calls would fail to compile if argument reordering was
 forbidden?

 spawnProcess("/usr/bin/sort", stdout: outputFile, stdin:
 inputFile);
 spawnProcess("/usr/bin/sort", stdin: inputFile, stdout:
 outputFile);

 From a usability perspective, it's completely insane for only
 one of these to work.
Without looking at the documentation, what are the parameters of this function blah(...) ?
My point is not that programmers should be able to write code without ever looking at documentation, it's that programmers should not have to do mindless busywork that the compiler could just as easily do for them.
If programmers don't read the documenation, then they're just begging for trouble. It shouldn't be necessary to read the documentation every time you use a function or other symbol from a library, but it's a serious problem if programmers think that they can get away with never reading the documentation to see how the code they're using is even supposed to work. - Jonathan M Davis
Jun 09
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/8/19 2:05 PM, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that have default 
 values, but what is the value in allowing the caller to reorder them?
Named arguments is useful mainly so one doesn't need to remember their order in large argument lists.
Jun 09
parent reply aliak <something something.com> writes:
On Sunday, 9 June 2019 at 07:51:18 UTC, Andrei Alexandrescu wrote:
 On 6/8/19 2:05 PM, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that have 
 default values, but what is the value in allowing the caller 
 to reorder them?
Named arguments is useful mainly so one doesn't need to remember their order in large argument lists.
When has anyone had a problem with unreorderable named arguments in functions with large argument lists? After using languages with unreorderable and reorderable named parameters. I only see a very mild benefit of programmer laziness for reorderable, and the larger downside of reader annoyance. I've felt no downsides of unreorderable (you generally look at the documentation, and type it in param by param, or copy paste the declaration, and if you get it wrong, the compiler tells you and you fix it).
Jun 09
next sibling parent reply aliak <something something.com> writes:
On Sunday, 9 June 2019 at 11:15:39 UTC, aliak wrote:
 On Sunday, 9 June 2019 at 07:51:18 UTC, Andrei Alexandrescu 
 wrote:
 On 6/8/19 2:05 PM, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that have 
 default values, but what is the value in allowing the caller 
 to reorder them?
Named arguments is useful mainly so one doesn't need to remember their order in large argument lists.
When has anyone had a problem with unreorderable named arguments in functions with large argument lists? After using languages with unreorderable and reorderable named parameters. I only see a very mild benefit of programmer laziness for reorderable, and the larger downside of reader annoyance. I've felt no downsides of unreorderable (you generally look at the documentation, and type it in param by param, or copy paste the declaration, and if you get it wrong, the compiler tells you and you fix it).
There're also some technical advantages/disadvantages to either or: 1) searchability is out the window if you allow reordering find "func(a:" will now not work 2) semantic overloading is out the window lets(int doA, int thenB int thenC) lets(int doA, int thenC, int thenB) I'm not sure what technical advantages reordering brings though. I also wonder what kind of overload resolution can be accomplished with reorderable and unreorderable, and also what kind of overload resolution is blocked with either of the two. I believe that should also be taken in to account to make a better decision here. Maybe the DIP can address that point as well? Cheers - Ali
Jun 09
parent reply aliak <something something.com> writes:
On Sunday, 9 June 2019 at 11:26:07 UTC, aliak wrote:
 On Sunday, 9 June 2019 at 11:15:39 UTC, aliak wrote:
 [...]
There're also some technical advantages/disadvantages to either or: 1) searchability is out the window if you allow reordering find "func(a:" will now not work 2) semantic overloading is out the window lets(int doA, int thenB int thenC) lets(int doA, int thenC, int thenB) I'm not sure what technical advantages reordering brings though. I also wonder what kind of overload resolution can be accomplished with reorderable and unreorderable, and also what kind of overload resolution is blocked with either of the two. I believe that should also be taken in to account to make a better decision here. Maybe the DIP can address that point as well? Cheers - Ali
Forgot another technical advantage: evaluation of arguments. With unreorderable it's obvious. With reorderable, as Walter pointed out, what't the order (parameter-wise or argument-wise).
Jun 09
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/9/19 7:27 AM, aliak wrote:
 With reorderable, as Walter pointed out, what't the order 
 (parameter-wise or argument-wise).
Lexical order of course.
Jun 09
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Sunday, 9 June 2019 at 19:43:54 UTC, Andrei Alexandrescu wrote:
 On 6/9/19 7:27 AM, aliak wrote:
 With reorderable, as Walter pointed out, what't the order 
 (parameter-wise or argument-wise).
Lexical order of course.
Lexical order of the definition or the caller? So far we have 1 for the caller and 1 for the definition. Both seem to think their choice is the obviously correct one :) > Patrick Schluter: > They are in the order of declaration of the function...There's no reason to evaluate it any other order as the code generation requires that the caller populates the registers/stack in the order the function expects. > Paul Backus: > Personally, I think the obviously-correct choice is to evaluate them in lexical order (i.e., order of the call).
Jun 09
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09.06.19 23:01, Jonathan Marler wrote:
 On Sunday, 9 June 2019 at 19:43:54 UTC, Andrei Alexandrescu wrote:
 On 6/9/19 7:27 AM, aliak wrote:
 With reorderable, as Walter pointed out, what't the order 
 (parameter-wise or argument-wise).
Lexical order of course.
Lexical order of the definition or the caller? ...
Lexical order means lexical order. It's the order in which the arguments are written in the source code.
 So far we have 1 for the caller and 1 for the definition.
This is simply not true. Count again.
 Both seem to 
 think their choice is the obviously correct one :)
 ...
One of those two is wrong, and is actually a minority.
    > Patrick Schluter:
    > They are in the order of declaration of the function...There's no 
 reason to evaluate it any other order ...
 ...
Clearly there are multiple reasons to do that.
    > Paul Backus:
    > Personally, I think the obviously-correct choice is to evaluate 
 them in lexical order (i.e., order of the call).
 
Yes.
Jun 09
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/9/19 5:01 PM, Jonathan Marler wrote:
 On Sunday, 9 June 2019 at 19:43:54 UTC, Andrei Alexandrescu wrote:
 On 6/9/19 7:27 AM, aliak wrote:
 With reorderable, as Walter pointed out, what't the order 
 (parameter-wise or argument-wise).
Lexical order of course.
Lexical order of the definition or the caller?
Order of the call. One doesn't need to examine the function declaration to figure out the order of evaluation at call site.
Jun 10
prev sibling parent reply Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Sunday, 9 June 2019 at 21:01:35 UTC, Jonathan Marler wrote:
 On Sunday, 9 June 2019 at 19:43:54 UTC, Andrei Alexandrescu 
 wrote:
 On 6/9/19 7:27 AM, aliak wrote:
 With reorderable, as Walter pointed out, what't the order 
 (parameter-wise or argument-wise).
Lexical order of course.
Lexical order of the definition or the caller? So far we have 1 for the caller and 1 for the definition. Both seem to think their choice is the obviously correct one :) > Patrick Schluter: > They are in the order of declaration of the function...There's no reason to evaluate it any other order as the code generation requires that the caller populates the registers/stack in the order the function expects. > Paul Backus: > Personally, I think the obviously-correct choice is to evaluate them in lexical order (i.e., order of the call).
That's probably a bottom up vs top down perception of things. When you learned the stuff at the assembly/object level you tend to see the things in cpu perspective, and there you tend to see the call convention for what it is pushing register in a specific order. If you came from the high level application level where the machine implementation is nothing more than a detail, you tend to don't care about the hoops the compiler/implementation has to go through to realize the abstraction the language presents (best example is the set types in Pascal where the elegance of 'if c in [a..z]' was loved by programmers, but resulted in an incredibly complex code). This said, the lexical order is after all the more abstract one and the complexity of it is imo manageable by the compiler so there's nothing that should preclude it, even if in my mental model that is closer to the implementation, would see callee order first.
Jun 10
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Jun 10, 2019 at 06:28:38PM +0000, Patrick Schluter via Digitalmars-d
wrote:
[...]
 If you came from the high level application level where the machine
 implementation is nothing more than a detail, you tend to don't care
 about the hoops the compiler/implementation has to go through to
 realize the abstraction the language presents (best example is the set
 types in Pascal where the elegance of 'if c in [a..z]' was loved by
 programmers, but resulted in an incredibly complex code).
Not disagreeing here, but couldn't resist the obligatory quote: People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird. -- D. Knuth T -- Some days you win; most days you lose.
Jun 10
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10.06.19 20:28, Patrick Schluter wrote:
 On Sunday, 9 June 2019 at 21:01:35 UTC, Jonathan Marler wrote:
 On Sunday, 9 June 2019 at 19:43:54 UTC, Andrei Alexandrescu wrote:
 On 6/9/19 7:27 AM, aliak wrote:
 With reorderable, as Walter pointed out, what't the order 
 (parameter-wise or argument-wise).
Lexical order of course.
Lexical order of the definition or the caller? So far we have 1 for the caller and 1 for the definition. Both seem to think their choice is the obviously correct one :)   > Patrick Schluter:   > They are in the order of declaration of the function...There's no reason to evaluate it any other order as the code generation requires that the caller populates the registers/stack in the order the function expects.   > Paul Backus:   > Personally, I think the obviously-correct choice is to evaluate them in lexical order (i.e., order of the call).
That's probably a bottom up vs top down perception of things. When you learned the stuff at the assembly/object level you tend to see the things in cpu perspective, and there you tend to see the call convention
With C compilers, where order of evaluation is arbitrary, usually you will see compilers using /reverse/ order.
 for what it is pushing register in a specific order.
This does not really make a lot of sense. Why would there be a preferred order to push registers that influences preferred order of arguments? The actual point is that for /some subset/ of the arguments (those that are actually pushed onto the stack instead of passed in registers), the calling convention will specify in which order they have to end up on the stack. But there is no rule that says you have to evaluate side-effects of arguments in the order they will end up on the stack!
 If you came from the high level application level where the machine 
 implementation is nothing more than a detail, you tend to don't care 
 about the hoops the compiler/implementation has to go through to realize 
 the abstraction the language presents (best example is the set types in 
 Pascal where the elegance of 'if c in [a..z]' was loved by programmers, 
 but resulted in an incredibly complex code).
 ...
I.e., some old Pascal compiler sucked.
 This said, the lexical order is after all the more abstract one and the 
 complexity of it is imo manageable by the compiler so there's nothing 
 that should preclude it, even if in my mental model that is closer to 
 the implementation, would see callee order first.
 
A good programmer understands multiple levels of abstraction at the same time, and evaluating in order of formal parameters is not actually "closer to the implementation". Furthermore, you can always change the evaluation order by defining some temporaries, if you think some other order will allow the compiler to do a better job using the limited available static information.
Jun 10
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/9/19 7:15 AM, aliak wrote:
 On Sunday, 9 June 2019 at 07:51:18 UTC, Andrei Alexandrescu wrote:
 On 6/8/19 2:05 PM, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that have default 
 values, but what is the value in allowing the caller to reorder them?
Named arguments is useful mainly so one doesn't need to remember their order in large argument lists.
When has anyone had a problem with unreorderable named arguments in functions with large argument lists?
This is a leading question. When has anyone hadn't?
 After using languages with unreorderable and reorderable named 
 parameters. I only see a very mild benefit of programmer laziness for 
 reorderable, and the larger downside of reader annoyance. I've felt no 
 downsides of unreorderable (you generally look at the documentation, and 
 type it in param by param, or copy paste the declaration, and if you get 
 it wrong, the compiler tells you and you fix it).
What would be those languages? The Wikipedia page https://en.wikipedia.org/wiki/Named_parameter mentions: "With named parameters, it is usually possible to provide the values in any arbitrary order, since the name attached to each value identifies its purpose. This reduces the connascence between parts of the program. A few languages use named parameters but still require the parameters to be provided in a specific order." So it looks like reordering is prevalently supported. The page https://rosettacode.org/wiki/Named_parameters mentions that the following languages do not support reordering (upon a quick look): Elixir, Fortran, Nemerle. Is this the company we want to be in? From what I see in a few popular languages: * Python: reordering is a feature. From https://treyhunner.com/2018/04/keyword-arguments-in-python: "When we use keyword/named arguments, it’s the name that matters, not the position" * C# 4: reordering is a feature. From https://en.wikipedia.org/wiki/C_Sharp_4.0#Optional_parameters_ nd_named_arguments: "Parameter names can be specified for both optional and required parameters, and can be used to improve readability or arbitrarily to reorder arguments in a call." * Ruby: reordering is a feature. From https://thoughtbot.com/blog/ruby-2-keyword-arguments: "Keyword arguments allow us to switch the order of the arguments, without affecting the behavior of the method" * Scala: reordering is a feature. From https://docs.scala-lang.org/tour/named-arguments.html: "Notice how the order of named arguments can be rearranged." That's why the "Related Work" section is crucial. It needs to make a careful account of experience in existing languages. For my money, named arguments with no reordering means we're wasting our time.
Jun 09
next sibling parent reply aliak <something something.com> writes:
On Sunday, 9 June 2019 at 19:42:19 UTC, Andrei Alexandrescu wrote:
 On 6/9/19 7:15 AM, aliak wrote:
 On Sunday, 9 June 2019 at 07:51:18 UTC, Andrei Alexandrescu 
 wrote:
 On 6/8/19 2:05 PM, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that have 
 default values, but what is the value in allowing the caller 
 to reorder them?
Named arguments is useful mainly so one doesn't need to remember their order in large argument lists.
When has anyone had a problem with unreorderable named arguments in functions with large argument lists?
This is a leading question. When has anyone hadn't?
When they had never hasn'ted of course.
 After using languages with unreorderable and reorderable named 
 parameters. I only see a very mild benefit of programmer 
 laziness for reorderable, and the larger downside of reader 
 annoyance. I've felt no downsides of unreorderable (you 
 generally look at the documentation, and type it in param by 
 param, or copy paste the declaration, and if you get it wrong, 
 the compiler tells you and you fix it).
What would be those languages? The Wikipedia page https://en.wikipedia.org/wiki/Named_parameter mentions:
Of the popular ones I guess those'd be objective-c and swift. Though reordering is prevalently supported indeed.
 "With named parameters, it is usually possible to provide the 
 values in any arbitrary order, since the name attached to each 
 value identifies its purpose. This reduces the connascence 
 between parts of the program. A few languages use named 
 parameters but still require the parameters to be provided in a 
 specific order."
🤔 connascence... hadn't thought of that... nice.
 That's why the "Related Work" section is crucial. It needs to 
 make a careful account of experience in existing languages. For 
 my money, named arguments with no reordering means we're 
 wasting our time.
Not sure if it's a waste of time without reordering as apple has been fine without it for decades and also maintained it with the new language - and at least I've never heard anyone complain. Maybe swift just got it because obj-c had it though [0]. Couldn't really find any official motivational text for it. I did find that swift had reorderable defaulted parameters [1], and the proposal to get rid of those basically concluded with "The core team prefers to encourage consistency at call sites." but not much else. And then rust was talking about it as well [2], but there's no consensus there on whether to allow reordering or not. The proposal allows for it, but there's mention of the danger of it in one of the threads. There is however a lot of ideas and thoughts in that thread that would be good to address in this DIP. [0]: https://www.reddit.com/r/swift/comments/5rlcnb/fixed_order_of_named_parameters/ [1]: https://github.com/apple/swift-evolution/blob/master/proposals/0060-defaulted-parameter-order.md [2]: https://internals.rust-lang.org/t/pre-rfc-named-arguments/3831
Jun 09
parent Jonathan Marler <johnnymarler gmail.com> writes:
On Sunday, 9 June 2019 at 22:49:11 UTC, aliak wrote:
 On Sunday, 9 June 2019 at 19:42:19 UTC, Andrei Alexandrescu 
 wrote:
 On 6/9/19 7:15 AM, aliak wrote:
 On Sunday, 9 June 2019 at 07:51:18 UTC, Andrei Alexandrescu 
 wrote:
 On 6/8/19 2:05 PM, Jonathan Marler wrote:
 I see value in allowing a caller to omit arguments that 
 have default values, but what is the value in allowing the 
 caller to reorder them?
Named arguments is useful mainly so one doesn't need to remember their order in large argument lists.
When has anyone had a problem with unreorderable named arguments in functions with large argument lists?
This is a leading question. When has anyone hadn't?
When they had never hasn'ted of course.
 After using languages with unreorderable and reorderable 
 named parameters. I only see a very mild benefit of 
 programmer laziness for reorderable, and the larger downside 
 of reader annoyance. I've felt no downsides of unreorderable 
 (you generally look at the documentation, and type it in 
 param by param, or copy paste the declaration, and if you get 
 it wrong, the compiler tells you and you fix it).
What would be those languages? The Wikipedia page https://en.wikipedia.org/wiki/Named_parameter mentions:
Of the popular ones I guess those'd be objective-c and swift. Though reordering is prevalently supported indeed.
 "With named parameters, it is usually possible to provide the 
 values in any arbitrary order, since the name attached to each 
 value identifies its purpose. This reduces the connascence 
 between parts of the program. A few languages use named 
 parameters but still require the parameters to be provided in 
 a specific order."
🤔 connascence... hadn't thought of that... nice.
 That's why the "Related Work" section is crucial. It needs to 
 make a careful account of experience in existing languages. 
 For my money, named arguments with no reordering means we're 
 wasting our time.
Not sure if it's a waste of time without reordering as apple has been fine without it for decades and also maintained it with the new language - and at least I've never heard anyone complain. Maybe swift just got it because obj-c had it though [0]. Couldn't really find any official motivational text for it. I did find that swift had reorderable defaulted parameters [1], and the proposal to get rid of those basically concluded with "The core team prefers to encourage consistency at call sites." but not much else. And then rust was talking about it as well [2], but there's no consensus there on whether to allow reordering or not. The proposal allows for it, but there's mention of the danger of it in one of the threads. There is however a lot of ideas and thoughts in that thread that would be good to address in this DIP. [0]: https://www.reddit.com/r/swift/comments/5rlcnb/fixed_order_of_named_parameters/ [1]: https://github.com/apple/swift-evolution/blob/master/proposals/0060-defaulted-parameter-order.md [2]: https://internals.rust-lang.org/t/pre-rfc-named-arguments/3831
Hey...rust stole my idea :) https://internals.rust-lang.org/t/pre-rfc-named-arguments/3831 See the "API authors are in control section". He recommends using `pub` as a parameter modifier to expose their names. > API authors are in control > Let’s start with the last point. Many proposals to add named arguments to Rust assumed that all arguments would become optional named arguments. However, this would make all the argument names part of the public API and renaming them would become a breaking change. > In this proposal I wish to give the ability to the API authors to choose if they want to commit to the argument names by making them part of the public API. Funny to read the comments and see similar debate for the same thing in a completely different community :)
Jun 10
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/9/2019 12:42 PM, Andrei Alexandrescu wrote:
 For my money, named arguments with 
 no reordering means we're wasting our time.
I agree. We'd just have to add it in later. I don't want to have to constantly explain why reordering isn't supported. Might as well do it right the first time, especially since it is simple and D already does this for field initializers.
Jun 09
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/5/19 9:03 AM, 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/9c9cc39246de4c449fe1e6cb6b27f7e426ff
eb9/DIPs/DIP1019.md 
[initially posted in the wrong thread, pasting here for conformity] Things that I think would make this DIP stronger: * The presence of the feature in other programming languages belongs in "rationale" if also the rationale pertaining to those other languages is present. Otherwise it's argument by majority. Normally "rationale" would stand on its own (possibly using examples drawn/inspired from other languages) and mention of other languages would go in the "related work" section (which presently is missing). ( Michael we need to make "Related Work" a required section.) * The example with "CalculateProduct(values, 7, false, null);" in the rationale should be completed with the best-of-the-breed solution in the current D language, i.e. using Flag. Currently Flag is not being discussed at all and it should because it is a workaround to named parameters (however insufficient as the proposal might argue). * The argument with repurposing argument is weak because code that doesn't use named parameters would be broken anyway, which makes the idea of repurposing parameters bad to start with. I suggest it be dropped, or mentioned later as a perk of named parameters. * "The relevance of forward declarations will become clear later." -> "Section xyz clarifies the relevance of forward declarations." * "Named arguments proposed by this DIP have no effect on the ordering of arguments in function calls." Related work will in all likelihood reveal that reordering arguments in large argument lists is a key advantage of named arguments. Not availing ourselves of that advantage is a serious issue that weakens the proposal. It must explain why it is not possible to allow reordering of arguments (or better yet work out the mechanics to allow it). * "Named arguments proposed by this DIP do not allow default parameters to be skipped." Not sure what "skipped" means in context; I assume it means some defaulted arguments would be left unspecified and other following them would be specified with non-default values. My understanding is that this is another key advantage of named arguments in related work - typically complex functions with large argument lists like CreateWindow, CreateArchive etc. would have many arguments defaulted to reasonable values, which then the caller can pick and choose which to customize. I assume a large part of what makes Python APIs so friendly is this ability. The DIP should explain why this is not desirable or achievable for the D language (or again better yet make it just work). * "Variadic arguments can be labeled with the name of the variadic parameter and a subscript." seems to have little value if there's only one variadic per function and all indexes must be specified in order. The DIP should explain why this feature (the index can be any compile-time expression... right?) is useful. * "If a function is defined with some of its parameter names omitted, arguments to those parameters can labeled with an empty name." The utility of this should be explained. * "This seems to be the biggest concern among people who are against named arguments." This is vague and nonscientific and has no place in a DIP. Who are those (does it even matter), where are the relevant exchanges, how did the author arrive at the conclusion that this is the biggest concern. The concern should be discussed at face value and if appropriate rebutted soundly with an analysis of the tradeoff (I assume it's not "all bad" vs "all good" but more like pros and cons). * "Allow calling the same function with a different set of parameter names." The advantage of this seems to be backward compatibility, but it endorses a technique that is questionable in the first place. * "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." The problem here is that all of these (easily anticipated as desirable) weaken the DIP by their absence from it.
Jun 07
next sibling parent reply Jon Degenhardt <jond noreply.com> writes:
On Saturday, 8 June 2019 at 06:44:56 UTC, Andrei Alexandrescu 
wrote:
 On 6/5/19 9:03 AM, 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
Things that I think would make this DIP stronger: * The presence of the feature in other programming languages belongs in "rationale" if also the rationale pertaining to those other languages is present. Otherwise it's argument by majority. Normally "rationale" would stand on its own (possibly using examples drawn/inspired from other languages) and mention of other languages would go in the "related work" section (which presently is missing).
Given that there are a fair number of programming languages that have implemented named parameters, it might make sense to go a bit further and provide a summary of the different goals and approaches that have been used elsewhere. That would make it easier to compare the proposal to related efforts. There may well be published papers that provide such comparisons. A starting point list of languages with named parameters can be found here: https://en.wikipedia.org/wiki/Named_parameter --Jon
Jun 08
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/8/19 3:02 PM, Jon Degenhardt wrote:
 On Saturday, 8 June 2019 at 06:44:56 UTC, Andrei Alexandrescu wrote:
 On 6/5/19 9:03 AM, 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/9c9cc39246de4c449fe1e6cb6b27f7e426ff
eb9/DIPs/DIP1019.md 
Things that I think would make this DIP stronger: * The presence of the feature in other programming languages belongs in "rationale" if also the rationale pertaining to those other languages is present. Otherwise it's argument by majority. Normally "rationale" would stand on its own (possibly using examples drawn/inspired from other languages) and mention of other languages would go in the "related work" section (which presently is missing).
Given that there are a fair number of programming languages that have implemented named parameters, it might make sense to go a bit further and provide a summary of the different goals and approaches that have been used elsewhere. That would make it easier to compare the proposal to related efforts. There may well be published papers that provide such comparisons. A starting point list of languages with named parameters can be found here: https://en.wikipedia.org/wiki/Named_parameter --Jon
Yes please!
Jun 09
prev sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Saturday, 8 June 2019 at 06:44:56 UTC, Andrei Alexandrescu 
wrote:
 On 6/5/19 9:03 AM, 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
[initially posted in the wrong thread, pasting here for conformity]
Thanks for the feedback! I will try to address some of your points.
 Things that I think would make this DIP stronger:

 * The presence of the feature in other programming languages 
 belongs in "rationale" if also the rationale pertaining to 
 those other languages is present. Otherwise it's argument by 
 majority. Normally "rationale" would stand on its own (possibly 
 using examples drawn/inspired from other languages) and mention 
 of other languages would go in the "related work" section 
 (which presently is missing).

 ( Michael we need to make "Related Work" a required section.)
Will do.
 * The example with "CalculateProduct(values, 7, false, null);" 
 in the rationale should be completed with the best-of-the-breed 
 solution in the current D language, i.e. using Flag. Currently 
 Flag is not being discussed at all and it should because it is 
 a workaround to named parameters (however insufficient as the 
 proposal might argue).
Will do.
 * The argument with repurposing argument is weak because code 
 that doesn't use named parameters would be broken anyway, which 
 makes the idea of repurposing parameters bad to start with. I 
 suggest it be dropped, or mentioned later as a perk of named 
 parameters.
The point is named parameters prevents silent breakage. Which I think is a significant benefit. Of course, code that do not use named parameters won't get the benefit of named parameters. This is just the natural of things and shouldn't be used as a point against the point.
 * "The relevance of forward declarations will become clear 
 later." -> "Section xyz clarifies the relevance of forward 
 declarations."

 * "Named arguments proposed by this DIP have no effect on the 
 ordering of arguments in function calls." Related work will in 
 all likelihood reveal that reordering arguments in large 
 argument lists is a key advantage of named arguments. Not 
 availing ourselves of that advantage is a serious issue that 
 weakens the proposal. It must explain why it is not possible to 
 allow reordering of arguments (or better yet work out the 
 mechanics to allow it).
Reordering is definitely a very important feature. However, this proposal is not going to be the last DIP about named parameters, as is stressed in the proposal itself. Generally, I think incremental improvements should be allowed.
 * "Named arguments proposed by this DIP do not allow default 
 parameters to be skipped." Not sure what "skipped" means in 
 context; I assume it means some defaulted arguments would be 
 left unspecified and other following them would be specified 
 with non-default values. My understanding is that this is 
 another key advantage of named arguments in related work - 
 typically complex functions with large argument lists like 
 CreateWindow, CreateArchive etc. would have many arguments 
 defaulted to reasonable values, which then the caller can pick 
 and choose which to customize. I assume a large part of what 
 makes Python APIs so friendly is this ability. The DIP should 
 explain why this is not desirable or achievable for the D 
 language (or again better yet make it just work).
Same as the above one.
 * "Variadic arguments can be labeled with the name of the 
 variadic parameter and a subscript." seems to have little value 
 if there's only one variadic per function and all indexes must 
 be specified in order. The DIP should explain why this feature 
 (the index can be any compile-time expression... right?) is 
 useful.
index can only be integer literals, as is specified in the "Grammar changes" section. This exists to avoid confusion that might arise from labeling multiple arguments with the same name.
 * "If a function is defined with some of its parameter names 
 omitted, arguments to those parameters can labeled with an 
 empty name." The utility of this should be explained.
This feature is here for completeness and consistency, so there is not a case where an argument cannot be labeled. Unless there is a strong disadvantage of allowing this, I think this should stay.
 * "This seems to be the biggest concern among people who are 
 against named arguments." This is vague and nonscientific and 
 has no place in a DIP. Who are those (does it even matter), 
 where are the relevant exchanges, how did the author arrive at 
 the conclusion that this is the biggest concern. The concern 
 should be discussed at face value and if appropriate rebutted 
 soundly with an analysis of the tradeoff (I assume it's not 
 "all bad" vs "all good" but more like pros and cons).
Good point.
 * "Allow calling the same function with a different set of 
 parameter names." The advantage of this seems to be backward 
 compatibility, but it endorses a technique that is questionable 
 in the first place.
Can you elaborate why is this questionable?
 * "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." 
 The problem here is that all of these (easily anticipated as 
 desirable) weaken the DIP by their absence from it.
The point I want to make it that you shouldn't compare this DIP to some idealized, optimal DIP you imagined. You should evaluate it by comparing it to what we have now. Especially for a DIP that allows (anticipates, even) further improvements. If this DIP is a net improvement, and no major concern exists against it, I don't see why it cannot be accepted just because it doesn't give us all the things we want at once.
Jun 08
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/8/19 3:58 PM, Yuxuan Shui wrote:
 
 Reordering is definitely a very important feature. However, this 
 proposal is not going to be the last DIP about named parameters, as is 
 stressed in the proposal itself.
 
 Generally, I think incremental improvements should be allowed.
Sadly my vast and mostly unsuccessful experience with programming language design is that such is not to be done incrementally. Never. I will oppose a DIP that argues its utility by means of possible future DIPs. (For measure, don't forget I do not hold decision power any longer.) For named arguments, I very strongly believe that any DIP that does not allow reordering is a stillborn.
Jun 09
next sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Sunday, 9 June 2019 at 07:55:50 UTC, Andrei Alexandrescu wrote:
 On 6/8/19 3:58 PM, Yuxuan Shui wrote:
 
 Reordering is definitely a very important feature. However, 
 this proposal is not going to be the last DIP about named 
 parameters, as is stressed in the proposal itself.
 
 Generally, I think incremental improvements should be allowed.
Sadly my vast and mostly unsuccessful experience with programming language design is that such is not to be done incrementally. Never. I will oppose a DIP that argues its utility by means of possible future DIPs. (For measure, don't forget I do not hold decision power any longer.) For named arguments, I very strongly believe that any DIP that does not allow reordering is a stillborn.
I agree. Reordering is the main motivation. I've lost count of how many times I've shaken my fist at the sky when trying to change the working directory when calling std.process.execute.
Jun 09
next sibling parent reply aliak <something something.com> writes:
On Sunday, 9 June 2019 at 11:54:25 UTC, Atila Neves wrote:
 On Sunday, 9 June 2019 at 07:55:50 UTC, Andrei Alexandrescu 
 wrote:
 On 6/8/19 3:58 PM, Yuxuan Shui wrote:
 
 Reordering is definitely a very important feature. However, 
 this proposal is not going to be the last DIP about named 
 parameters, as is stressed in the proposal itself.
 
 Generally, I think incremental improvements should be allowed.
Sadly my vast and mostly unsuccessful experience with programming language design is that such is not to be done incrementally. Never. I will oppose a DIP that argues its utility by means of possible future DIPs. (For measure, don't forget I do not hold decision power any longer.) For named arguments, I very strongly believe that any DIP that does not allow reordering is a stillborn.
I agree. Reordering is the main motivation. I've lost count of how many times I've shaken my fist at the sky when trying to change the working directory when calling std.process.execute.
I'm curious what the dev process is here? You write a function, start filling in it's parameters and you get it wrong. Ok, so you check the docs right? And then you fill in the arguments while looking at the docs right? Or? Also do you think you'll have a similar experience with reorderable named parameters where instead of the position it is now the name of the argument? And then on top of that, if we allow non-named parameters to mix with named parameters, then what does reordering give you?
Jun 09
next sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Sunday, 9 June 2019 at 13:39:34 UTC, aliak wrote:
 On Sunday, 9 June 2019 at 11:54:25 UTC, Atila Neves wrote:
 On Sunday, 9 June 2019 at 07:55:50 UTC, Andrei Alexandrescu 
 wrote:
 On 6/8/19 3:58 PM, Yuxuan Shui wrote:
 
 Reordering is definitely a very important feature. However, 
 this proposal is not going to be the last DIP about named 
 parameters, as is stressed in the proposal itself.
 
 Generally, I think incremental improvements should be 
 allowed.
Sadly my vast and mostly unsuccessful experience with programming language design is that such is not to be done incrementally. Never. I will oppose a DIP that argues its utility by means of possible future DIPs. (For measure, don't forget I do not hold decision power any longer.) For named arguments, I very strongly believe that any DIP that does not allow reordering is a stillborn.
I agree. Reordering is the main motivation. I've lost count of how many times I've shaken my fist at the sky when trying to change the working directory when calling std.process.execute.
I'm curious what the dev process is here? You write a function, start filling in it's parameters and you get it wrong. Ok, so you check the docs right?
Most times the compiler complains.
 And then you fill in the arguments while looking at the docs 
 right? Or?
I fix the call based on the compiler error. I may or may not look at the function declaration.
 Also do you think you'll have a similar experience with 
 reorderable named parameters where instead of the position it 
 is now the name of the argument?
The hypothetical isn't needed, I already program that way when I can: https://github.com/atilaneves/kwargs Telling the compiler which argument matches each parameter with a type name or variable name seems, to me, to be a minor distinction. They're both symbols.
 And then on top of that, if we allow non-named parameters to 
 mix with named parameters, then what does reordering give you?
I thought I already covered that with my std.process.execute example. Right now I have to do this: auto myExecute(string[] args, string workDir) { import std.process: Config, execute; const string[string] env; const config = Config.none; size_t maxOutput = size_t.max; return execute(args, env, config, maxOutput, workDir); } When really I just want to: import std.process: execute; execute(args, WorkDir("~/foo/bar")); // or workdir: "~/foo/bar", or whatever I've typed the former more times than I can count, despite never having cared about changing the default values of the intermediate arguments.
Jun 09
parent Aliak <something something.com> writes:
On Sunday, 9 June 2019 at 17:04:12 UTC, Atila Neves wrote:
 On Sunday, 9 June 2019 at 13:39:34 UTC, aliak wrote:
 [...]
Most times the compiler complains.
 [...]
I fix the call based on the compiler error. I may or may not look at the function declaration. [...]
You can have skip default behavior with unorderable as well.
Jun 09
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/9/19 9:39 AM, aliak wrote:
 On Sunday, 9 June 2019 at 11:54:25 UTC, Atila Neves wrote:
 On Sunday, 9 June 2019 at 07:55:50 UTC, Andrei Alexandrescu wrote:
 On 6/8/19 3:58 PM, Yuxuan Shui wrote:
 Reordering is definitely a very important feature. However, this 
 proposal is not going to be the last DIP about named parameters, as 
 is stressed in the proposal itself.

 Generally, I think incremental improvements should be allowed.
Sadly my vast and mostly unsuccessful experience with programming language design is that such is not to be done incrementally. Never. I will oppose a DIP that argues its utility by means of possible future DIPs. (For measure, don't forget I do not hold decision power any longer.) For named arguments, I very strongly believe that any DIP that does not allow reordering is a stillborn.
I agree. Reordering is the main motivation. I've lost count of how many times I've shaken my fist at the sky when trying to change the working directory when calling std.process.execute.
I'm curious what the dev process is here? You write a function, start filling in it's parameters and you get it wrong. Ok, so you check the docs right? And then you fill in the arguments while looking at the docs right? Or? Also do you think you'll have a similar experience with reorderable named parameters where instead of the position it is now the name of the argument? And then on top of that, if we allow non-named parameters to mix with named parameters, then what does reordering give you?
A missing straitjacket.
Jun 09
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/9/2019 4:54 AM, Atila Neves wrote:
 I've lost count of how many times 
 I've shaken my fist at the sky when trying to change the working directory
when 
 calling std.process.execute.
https://i.kym-cdn.com/entries/icons/original/000/019/304/old.jpg
Jun 09
prev sibling parent Yuxuan Shui <yshuiv7 gmail.com> writes:
On Sunday, 9 June 2019 at 07:55:50 UTC, Andrei Alexandrescu wrote:
 On 6/8/19 3:58 PM, Yuxuan Shui wrote:
 
 Reordering is definitely a very important feature. However, 
 this proposal is not going to be the last DIP about named 
 parameters, as is stressed in the proposal itself.
 
 Generally, I think incremental improvements should be allowed.
Sadly my vast and mostly unsuccessful experience with programming language design is that such is not to be done incrementally. Never. I will oppose a DIP that argues its utility by means of possible future DIPs. (For measure, don't forget I do not hold decision power any longer.)
Care to share your experience? Statements like this will be much more helpful when paired with the process of how they are reached.
Jun 09
prev sibling parent Mike Parker <aldacron gmail.com> writes:
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
I've just discovered that I had locally committed the edits I made to this DIP but never pushed to them to the repository. That's why it was marked as "Post-Community 1" and not "Community Review Round 2". You've all been reviewing the correct content--the DIP author's revisions--just without my copy edits. So all of the feedback so far is perfectly valid. I'm only posting for completeness. The edited version is here: https://github.com/dlang/DIPs/blob/e3037dd967b5672e48d0f09b85f082540155d83b/DIPs/DIP1019.md
Jun 10