digitalmars.D - DIP 1019--Named Arguments Lite--Community Review Round 1
- Mike Parker (14/14) Feb 15 2019 This is the feedback thread for the first round of Community
- Atila Neves (3/6) Feb 15 2019 I'd add my library too as a possible library solution:
- Francesco Mecca (16/23) Feb 15 2019 I think that the solution proposed by Atila is better for the
- 12345swordy (5/14) Feb 15 2019 You miss the other reason on why it is not enough: Compile time
- JN (4/7) Feb 15 2019 Also, when doing a typo, rather than a nice error message "No
- Atila Neves (4/12) Feb 18 2019 Have you tried it? I attempted to static assert on nonsense with
- Francesco Mecca (10/26) Feb 16 2019 I have messed with kwargs and compile time doesn't seem to be an
- aliak (17/46) Feb 16 2019 kwargs is not scalable. You can't use the same types as
- Atila Neves (4/20) Feb 18 2019 Run-time? I'd expect the call to inlined. It'll definitely take
- Rubn (87/109) Feb 18 2019 The compiler isn't some magic device, your implementation is not
-
Atila Neves
(39/69)
Feb 19 2019
- Atila Neves (4/22) Feb 18 2019 That's not true - it works fine with regular functions.
- Paul Backus (25/27) Feb 15 2019 The fact that named arguments, as proposed, require both the
- Yuxuan Shui (17/33) Feb 16 2019 Named parameters have to be opt-in at both sides.
- 12345swordy (6/8) Feb 16 2019 If many people don't like this, then what? That should be
- Olivier FAURE (3/5) Feb 16 2019 Please calm down. We're just discussing merits, there's no need
- 12345swordy (8/14) Feb 16 2019 I am calm down, as the other poster said, we shouldn't accept
- Rubn (5/11) Feb 17 2019 Telling someone that is angry or distressed to calm down is just
- Paul Backus (5/12) Feb 16 2019 I don't think a DIP that makes the language worse should be
- 12345swordy (9/23) Feb 15 2019 I think named parameters should be opt-out rather then opt-in. It
- Guillaume Piolat (4/6) Feb 15 2019 - new function attribute is almost an automatic "no, thanks" from
- Ron Tarrant (8/9) Jun 07 2019 Yeah, that bothers me, too.
- Mike Parker (6/6) Jun 07 2019 I'd just like to point out to everyone that this thread is for
- aliak (78/80) Feb 15 2019 Wee! Named arguments :D
- Yuxuan Shui (18/91) Feb 15 2019 I was reluctant about add reordering too. The first version of
- 12345swordy (19/20) Feb 15 2019 Increasing the chance of this DIP being accepted by avoiding code
- Paul Backus (7/15) Feb 15 2019 It's actually worse than that--the purpose of @named is not to
- 12345swordy (15/34) Feb 15 2019 Which it is a non-issue in other languages such as C# as the
- Yuxuan Shui (5/25) Feb 15 2019 I am not saying "we should never break any code". I am deferring
- 12345swordy (4/10) Feb 15 2019 Why? We need to get it right the first time, as
- Yuxuan Shui (3/14) Feb 15 2019 So I don't want this proposal to be rejected.
- 12345swordy (19/36) Feb 15 2019 There are severe usability disadvantages that outweigh
- Olivier FAURE (22/26) Feb 16 2019 I think that, at least, you should include more details in the
- Olivier FAURE (3/8) Feb 16 2019 I forgot to say, thank you for your work on this DIP, and for
- Ron J (9/13) Feb 15 2019 I agree with this and despite breaking code indeed sucks, for a
- 12345swordy (7/20) Feb 15 2019 The "Old Way" aka C++98 will still be used simply because they
- aliak (47/126) Feb 16 2019 Yeah, I understand that. Though, just for the record if it came
- Jacob Shtokolov (17/19) Feb 15 2019 I think the "Completeness" section contains some arguable points.
- Yuxuan Shui (5/23) Feb 15 2019 This proposal is written purposefully to minimized its scope.
- Johannes Loher (41/46) Feb 15 2019 All in all, DIP 1019 looks quite interesting and also primising to me. I
- Yuxuan Shui (11/64) Feb 15 2019 Thanks for pointing these out, they will be fixed in the next
- Paul Backus (13/20) Feb 15 2019 In my experience, one of the greatest benefits of argument
- aliak (6/30) Feb 16 2019 Being able to leave out arguments would be hugely beneficial to
- Golden Rockefeller (25/39) Feb 15 2019 As another alternative, named parameters can be implemented using
- 12345swordy (3/49) Feb 15 2019 The downside to your solution is an increases in memory.
- Basile B. (7/9) Feb 16 2019 Tuples exist as an internal compiler type. The thing is just that
- Rubn (16/30) Feb 15 2019 drawRect(x: 0, y: 0, width: 1, height: 1);
- Yuxuan Shui (3/12) Feb 16 2019 Good point. I will fix this in next revision.
- Andre Pany (11/25) Feb 16 2019 With the struct initialization DIP there will come also named
- Cym13 (23/33) Feb 17 2019 I 100% support that. Relying on struct initialization is both the
- Cym13 (2/3) Feb 17 2019 I obviously meant: S args = { b: 43 };
- Yuxuan Shui (6/31) Feb 17 2019 Sure, but it has the exactly same property as @named: it's opt-in.
- Andre Pany (4/13) Feb 17 2019 It already exists std.traits: ParameterIdentifierTuple
- Vladimir Panteleev (39/47) Feb 16 2019 Named arguments is the #1 missing language feature in my personal
- Yuxuan Shui (20/69) Feb 16 2019 Good point.
- Vladimir Panteleev (30/37) Feb 17 2019 Sorry, but I will vote against a DIP with @named. With no
- Rubn (29/46) Feb 17 2019 I'd say enabling named parameters for everything would be better
- Yuxuan Shui (7/35) Feb 17 2019 This is allowed, _right now_. This is not an addition made by
- 12345swordy (4/7) Feb 17 2019 A better solution would be allowing nameless parameters functions
- Alex (14/21) Feb 17 2019 This possibility exists already via variadic templates and via
- Rubn (3/10) Feb 17 2019 That'd be worse, it'd make code less readable, the opposite of
- 12345swordy (15/26) Feb 17 2019 That is only if you are so worried about "parameter name becomes
- JN (14/21) Feb 17 2019 While I still think @named attribute feels weird, I know at least
- 12345swordy (5/27) Feb 17 2019 Even though that is interesting, what is being currently
- Rubn (20/66) Feb 17 2019 Yes that's very different from what you want to implement it. See
- Yuxuan Shui (7/36) Feb 17 2019 This is not valid under this DIP.
- Yuxuan Shui (17/17) Feb 17 2019 After thinking about the feedback so far, I currently plan to
- 12345swordy (5/15) Feb 17 2019 It is an issue if you are concern about compile time cost and
- RazvanN (21/40) Feb 18 2019 How about this: simply adding the ability to name the argument
- RazvanN (4/26) Feb 18 2019 I forgot to mention optional parameters; if there are any
- 12345swordy (2/7) Feb 18 2019 Now this is a solution that I can get behind.
- Seb (6/18) Feb 18 2019 1) What about typos/wrong names?
- RazvanN (8/30) Feb 18 2019 Easy: you print the parameters that do not match: "Unknown
- David Bennett (16/19) Mar 21 2019 Would you also be able to confirm how this DIP handles default
- Yuxuan Shui (6/26) Mar 22 2019 This DIP won't support template arguments.
- David Bennett (5/12) Apr 01 2019 That is unfortunate as its the part that gives me the most pain
- Rubn (6/56) Feb 17 2019 How does it decide which function to call in this case, straight
- Joseph Rushton Wakeling (9/15) Feb 27 2019 That seems to be a misunderstanding of what that example does.
- SimonN (14/15) Feb 18 2019 I discourage @named, too.
- Elronnd (5/5) Feb 17 2019 I might be misunderstanding something, but with this code:
- Paul Backus (8/13) Feb 17 2019 All declarations with the same signature must refer to the same
- Jonathan M Davis (33/48) Feb 26 2019 I honestly don't understand the whole deal about discussing "repurposing...
- aliak (46/50) Feb 27 2019 Curious. How come?
- Rubn (9/42) Feb 28 2019 I don't agree with this at all. The feature becomes all but
- Joseph Rushton Wakeling (19/26) Mar 03 2019 It's not comparable to changing the variable name of a struct,
- Olivier FAURE (5/9) Mar 03 2019 I think you're overstating how big the responsibility is.
- Joseph Rushton Wakeling (5/8) Mar 03 2019 Well, since the current DIP is entirely opt-in from the function
- Olivier FAURE (11/15) Mar 04 2019 My point was, the DIP should be opt-out, because even then
- H. S. Teoh (9/25) Mar 04 2019 IMNSHO, even if parameter names aren't important information to keep
- Yuxuan Shui (6/21) Mar 22 2019 I agree that, having named arguments as the default would be
- Paul Backus (11/16) Mar 22 2019 Deprecation is typically used for changes to existing
- Yuxuan Shui (3/30) Mar 04 2019 Agree completely. Finally someone arguing from this side :)
- Joseph Rushton Wakeling (109/109) Feb 27 2019 I would broadly second Jonathan's remarks above:
- JN (7/19) Feb 27 2019 Virtually all of them is a bit of a simplification. C#, Kotlin,
- Daniel N (12/19) Feb 27 2019 It would be great indeed, but insufficient.
- Joseph Rushton Wakeling (22/33) Mar 03 2019 I wonder if you have a real-world example of this requirement
- Yuxuan Shui (4/11) Mar 04 2019 I think this approach gives every parameter a default value, and
- Joseph Rushton Wakeling (4/7) Mar 04 2019 Agreed. It was an example of how to solve (essentially within
- FeepingCreature (38/101) Feb 28 2019 Yes it does!! That is in fact the main argument for it! It allows
- Dominikus Dittes Scherkl (6/10) Feb 28 2019 A function taking more than 2 parameters is a design flaw on its
- FeepingCreature (9/13) Feb 28 2019 Considering D is billed as a multiparadigm language, I'd be
- Joseph Rushton Wakeling (33/53) Mar 03 2019 This could sometimes be nice, but the question is whether the
- Dukc (13/15) Feb 27 2019 The proposal mentioned that having two @named functions with same
- Olivier FAURE (13/16) Feb 28 2019 No, it mentions that having two @named prototypes for the same
- Joseph Rushton Wakeling (9/22) Mar 01 2019 Is the idea here that you can effectively define "aliases" for
- Yuxuan Shui (5/15) Mar 04 2019 Function names won't be included in mangling. It is a bit
- Andrei Alexandrescu (63/67) Jun 06 2019 Things that I think would make this DIP stronger:
- H. S. Teoh (15/40) Jun 06 2019 [...]
This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment by the language maintainers. Please familiarize yourself with the documentation for the Community Review before participating. https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review Thanks in advance to all who participate.
Feb 15 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": [...]I'd add my library too as a possible library solution: https://github.com/atilaneves/kwargs
Feb 15 2019
On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:I think that the solution proposed by Atila is better for the following reasons: 1. it is a library solution 2. allows both the user and the author of a library to specify functions with named parameters 3. it is very lightweight But it is not enough for the following reasons: 1. Works only on templates (I'd like someone to explain to me why) 2. Is opinionated about using ad-hoc types to represent data (the opposite of http://wiki.c2.com/?PrimitiveObsession) If there is a consensus against primitive obsessions I think it would be better to solve point 1 and leave the decision to library authors to implement named parameters function or users to make their wrappers. This opt-in behaviour is not different from what it is provided by the DIPThis is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": [...]I'd add my library too as a possible library solution: https://github.com/atilaneves/kwargs
Feb 15 2019
On Friday, 15 February 2019 at 17:38:23 UTC, Francesco Mecca wrote:On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:You miss the other reason on why it is not enough: Compile time and run-time performance penalty. -Alex[...]I think that the solution proposed by Atila is better for the following reasons: 1. it is a library solution 2. allows both the user and the author of a library to specify functions with named parameters 3. it is very lightweight [...]
Feb 15 2019
On Friday, 15 February 2019 at 17:43:52 UTC, 12345swordy wrote:You miss the other reason on why it is not enough: Compile time and run-time performance penalty. -AlexAlso, when doing a typo, rather than a nice error message "No named argument defined for function foo()", you'd probably get few screens of template vomit :)
Feb 15 2019
On Friday, 15 February 2019 at 17:57:38 UTC, JN wrote:On Friday, 15 February 2019 at 17:43:52 UTC, 12345swordy wrote:Have you tried it? I attempted to static assert on nonsense with proper error messages. If you did and got terrible error messages, please file a github issue.You miss the other reason on why it is not enough: Compile time and run-time performance penalty. -AlexAlso, when doing a typo, rather than a nice error message "No named argument defined for function foo()", you'd probably get few screens of template vomit :)
Feb 18 2019
On Friday, 15 February 2019 at 17:43:52 UTC, 12345swordy wrote:On Friday, 15 February 2019 at 17:38:23 UTC, Francesco Mecca wrote:I have messed with kwargs and compile time doesn't seem to be an issue. At least it is not noticeable to me and I have a quite old dual core cpu. What kind of runtime penalty do you incur when using the library? To me it seems that the only penalty would be error messages. Also, kwargs allows unordered arguments and that is the path of lowest friction for people coming from languages with named parameters function (python on top of my mind). It makes sense if you want to improve readibility.On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:You miss the other reason on why it is not enough: Compile time and run-time performance penalty. -Alex[...]I think that the solution proposed by Atila is better for the following reasons: 1. it is a library solution 2. allows both the user and the author of a library to specify functions with named parameters 3. it is very lightweight [...]
Feb 16 2019
On Saturday, 16 February 2019 at 10:02:02 UTC, Francesco Mecca wrote:On Friday, 15 February 2019 at 17:43:52 UTC, 12345swordy wrote:kwargs is not scalable. You can't use the same types as parameters and you have to create a new type for each parameter. It's cumbersome and clunky and it relies on (unenforceable) convention to make the call site more readable. And it doesn't allow the API author to dictate how their function should be called. Named arguments is not a necessary feature of a language at all, it's only useful for maintenance and readability. There're no technical advantages to the api author, only psychological and aesthetic advantages to the api user, and the many code reviewers and maintainers who will follow them. Ok there is one technical advantage when it comes to overloads (See a post above). Maybe there're more ... 🤔🤷♂️ Cheers, - AliOn Friday, 15 February 2019 at 17:38:23 UTC, Francesco Mecca wrote:I have messed with kwargs and compile time doesn't seem to be an issue. At least it is not noticeable to me and I have a quite old dual core cpu. What kind of runtime penalty do you incur when using the library? To me it seems that the only penalty would be error messages. Also, kwargs allows unordered arguments and that is the path of lowest friction for people coming from languages with named parameters function (python on top of my mind). It makes sense if you want to improve readibility.On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:You miss the other reason on why it is not enough: Compile time and run-time performance penalty. -Alex[...]I think that the solution proposed by Atila is better for the following reasons: 1. it is a library solution 2. allows both the user and the author of a library to specify functions with named parameters 3. it is very lightweight [...]
Feb 16 2019
On Friday, 15 February 2019 at 17:43:52 UTC, 12345swordy wrote:On Friday, 15 February 2019 at 17:38:23 UTC, Francesco Mecca wrote:Run-time? I'd expect the call to inlined. It'll definitely take longer to compile though, but I'm at a loss why named parameters in the compiler are expected to be free.On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:You miss the other reason on why it is not enough: Compile time and run-time performance penalty. -Alex[...]I think that the solution proposed by Atila is better for the following reasons: 1. it is a library solution 2. allows both the user and the author of a library to specify functions with named parameters 3. it is very lightweight [...]
Feb 18 2019
On Monday, 18 February 2019 at 10:17:32 UTC, Atila Neves wrote:On Friday, 15 February 2019 at 17:43:52 UTC, 12345swordy wrote:The compiler isn't some magic device, your implementation is not easily optimized out to have no runtime cost. Even LDC has trouble optimizing it, and forget about DMD. struct Foo { int[1024] value; } void foo(ref Foo faa ) { import core.stdc.stdio : printf; foreach(int i, ref v; faa.value) { printf("%d", v); } } alias slowFoo = kwargify!foo; void func() { import std.stdio; Foo f; foreach(int i, ref v; f.value) { writeln("%d", v); } slowFoo( f ); foreach(int i, ref v; f.value) { writeln("%d", v); } } void example.func(): push rbp push r15 push r14 push rbx sub rsp, 8200 lea rdi, [rsp + 4104] xor ebx, ebx xor esi, esi mov edx, 4096 call memset PLT lea r15, [rsp + 8] lea r14, [rip + .L.str.1] .LBB1_1: mov ebp, dword ptr [rsp + 4*rbx + 4104] mov rdi, r15 call property trusted std.stdio.File std.stdio.trustedStdout() PLT mov esi, 10 mov ecx, 2 mov rdi, r15 mov edx, ebp mov r8, r14 call safe void std.stdio.File.write!(immutable(char)[], int, char).write(immutable(char)[], int, char) PLT mov rdi, r15 call safe void std.stdio.File.__dtor() PLT add rbx, 1 cmp rbx, 1024 jb .LBB1_1 lea rdi, [rsp + 8] lea rsi, [rsp + 4104] mov edx, 4096 call memcpy PLT <-------------------- lea rbx, [rip + .L.str.1] xor ebp, ebp .LBB1_4: mov esi, dword ptr [rsp + 4*rbp + 8] xor eax, eax mov rdi, rbx call printf PLT <------------------- add rbp, 1 cmp rbp, 1024 jne .LBB1_4 xor ebx, ebx lea r15, [rsp + 8] lea r14, [rip + .L.str.1] https://godbolt.org/z/6Tu8V7 As you can it is unable to optimize the extra copy that your implementation does by having to build a tuple before passing it to the function. No one is arguing that named parameters that are built in will be free. But it will be way faster as the compiler knows exactly what you are doing, not the hacky workaround you have that is severally limited (no templates, distinguished by types not "names" only allows you to reorder parameters all but useless for default types like int/float). Your implementation is extremely slow, both increasing compile times and decreasing runtime performance. All for the purpose of simply making code more readable. That's not a worthwhile trade off for the performance hit in both aspects.On Friday, 15 February 2019 at 17:38:23 UTC, Francesco Mecca wrote:Run-time? I'd expect the call to inlined. It'll definitely take longer to compile though, but I'm at a loss why named parameters in the compiler are expected to be free.On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:You miss the other reason on why it is not enough: Compile time and run-time performance penalty. -Alex[...]I think that the solution proposed by Atila is better for the following reasons: 1. it is a library solution 2. allows both the user and the author of a library to specify functions with named parameters 3. it is very lightweight [...]
Feb 18 2019
On Monday, 18 February 2019 at 13:18:15 UTC, Rubn wrote:On Monday, 18 February 2019 at 10:17:32 UTC, Atila Neves wrote:<snip> Good shout, thanks for bringing that up. I fixed this in version 0.0.2 (just pushed), and now both `callSlowFoo` and `callFastFoo` below yield the exact same assembly with ldc, and the function calls were inlined: ---------------------------------------------- import kwargs; struct Foo { int[1024] value; } void fastFoo(ref Foo faa) { import core.stdc.stdio: printf; foreach(int i, ref v; faa.value) { printf("%d ", v); } printf("\n"); } alias slowFoo = kwargify!fastFoo; void callSlowFoo() { Foo foo; initFoo(foo); slowFoo(foo); } void callFastFoo() { Foo foo; initFoo(foo); fastFoo(foo); } void initFoo(ref Foo foo) { foreach(int i, ref v; foo.value) { v = i; } } void main() { callSlowFoo; // callFastFoo; // it's the same! } ----------------------------------------------On Friday, 15 February 2019 at 17:43:52 UTC, 12345swordy wrote:The compiler isn't some magic device, your implementation is not easily optimized out to have no runtime cost. Even LDC has trouble optimizing it, and forget about DMD. struct Foo { int[1024] value; }On Friday, 15 February 2019 at 17:38:23 UTC, Francesco Mecca wrote:Run-time? I'd expect the call to inlined. It'll definitely take longer to compile though, but I'm at a loss why named parameters in the compiler are expected to be free.On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:You miss the other reason on why it is not enough: Compile time and run-time performance penalty. -Alex[...]I think that the solution proposed by Atila is better for the following reasons: 1. it is a library solution 2. allows both the user and the author of a library to specify functions with named parameters 3. it is very lightweight [...]
Feb 19 2019
On Friday, 15 February 2019 at 17:38:23 UTC, Francesco Mecca wrote:On Friday, 15 February 2019 at 13:49:04 UTC, Atila Neves wrote:That's not true - it works fine with regular functions.On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:I think that the solution proposed by Atila is better for the following reasons: 1. it is a library solution 2. allows both the user and the author of a library to specify functions with named parameters 3. it is very lightweight But it is not enough for the following reasons: 1. Works only on templates (I'd like someone to explain to me why)[...]I'd add my library too as a possible library solution: https://github.com/atilaneves/kwargs2. Is opinionated about using ad-hoc types to represent data (the opposite of http://wiki.c2.com/?PrimitiveObsession)Yes. I consider this to be a good thing, but then again, I would.
Feb 18 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite":The fact that named arguments, as proposed, require both the caller *and* the callee to opt-in seems like it would make them almost useless in practice. Even if someone's willing to put in the effort of going through all of Phobos to figure out which functions should be annotated with named, that still leaves all of the packages on code.dlang.org to deal with. Realistically, a lot of existing code will never be updated to work with this feature, even if it could benefit from it. It's also a pretty unsightly wart for newcomers to D to first learn that D supports named arguments (hooray!), and then find out that no, they can't use them with <insert package here> (boo!), because the author of that package hasn't "said the magic word" to enable them. I understand that the intent is to avoid unintentional breakage, but this feature is already opt-in from the caller's side. If someone wants to write code that's robust against parameter name changes, they can do it by not using named arguments in the first place. And, as noted in the DIP itself, there are still opportunities for accidental breakage even with named, when the caller fails to re-compile their code after a parameter name change. Parameter lock-in is definitely a legitimate concern, but IMHO adding a neutered version of named arguments like this one to the language would be worse than not having named arguments at all.
Feb 15 2019
On Friday, 15 February 2019 at 14:23:06 UTC, Paul Backus wrote:On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:Named parameters have to be opt-in at both sides. For the caller side, they can choose to not call the function with names so they can be robust against name changes (as you said). For the callee side, opt into named parameter create extra responsibility for them (e.g. they need to create new prototypes if they want to change parameter names). So if they don't want this responsibility, they can choose to not opt-inThis is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite":[snip] I understand that the intent is to avoid unintentional breakage, but this feature is already opt-in from the caller's side. If someone wants to write code that's robust against parameter name changes, they can do it by not using named arguments in the first place.And, as noted in the DIP itself, there are still opportunities for accidental breakage even with named, when the caller fails to re-compile their code after a parameter name change.I am not quite sure what you mean by this. A name change either changes the semantic of the parameters, in which case the caller won't realize their is a breakage until they recompile. But this kind of breakage is always intentional from the callee side. A pure parameter name change won't break anything even if caller doesn't recompile.Parameter lock-in is definitely a legitimate concern, but IMHO adding a neutered version of named arguments like this one to the language would be worse than not having named arguments at all.If someone doesn't like this, they can come up with a DIP to deprecate the named attribute in the future.
Feb 16 2019
On Saturday, 16 February 2019 at 14:04:44 UTC, Yuxuan Shui wrote:If someone doesn't like this, they can come up with a DIP to deprecate the named attribute in the future.If many people don't like this, then what? That should be sufficient grounds of rejection of the DIP itself. I *WILL* oppose this dip in it's entirely unless you remove the named attribute requirement from it. -Alex
Feb 16 2019
On Saturday, 16 February 2019 at 16:09:59 UTC, 12345swordy wrote:I *WILL* oppose this dip in it's entirely unless you remove the named attribute requirement from it.Please calm down. We're just discussing merits, there's no need for ultimatums.
Feb 16 2019
On Sunday, 17 February 2019 at 00:41:24 UTC, Olivier FAURE wrote:On Saturday, 16 February 2019 at 16:09:59 UTC, 12345swordy wrote:I am calm down, as the other poster said, we shouldn't accept this dip on the assumption that someone somewhere will write a DIP that will deprecated named. If that were the case, then this dip is bad to begin with. Expressing my strong objections to this is no way me being not calm, and I would appreciated that you didn't misinterpret my post. -AlexI *WILL* oppose this dip in it's entirely unless you remove the named attribute requirement from it.Please calm down. We're just discussing merits, there's no need for ultimatums.
Feb 16 2019
On Sunday, 17 February 2019 at 00:41:24 UTC, Olivier FAURE wrote:On Saturday, 16 February 2019 at 16:09:59 UTC, 12345swordy wrote:Telling someone that is angry or distressed to calm down is just about the worse thing you could say to them. Just saying, if were you were trying to calm someone down, you would have just been agitating them further.I *WILL* oppose this dip in it's entirely unless you remove the named attribute requirement from it.Please calm down. We're just discussing merits, there's no need for ultimatums.
Feb 17 2019
On Saturday, 16 February 2019 at 14:04:44 UTC, Yuxuan Shui wrote:On Friday, 15 February 2019 at 14:23:06 UTC, Paul Backus wrote:I don't think a DIP that makes the language worse should be accepted simply because someone, someday, may write a new DIP that makes it better again. And I would be very surprised if Walter and Andrei felt differently.Parameter lock-in is definitely a legitimate concern, but IMHO adding a neutered version of named arguments like this one to the language would be worse than not having named arguments at all.If someone doesn't like this, they can come up with a DIP to deprecate the named attribute in the future.
Feb 16 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment by the language maintainers. Please familiarize yourself with the documentation for the Community Review before participating. https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review Thanks in advance to all who participate.I think named parameters should be opt-out rather then opt-in. It seems like a hassle for the developer to update your functions to support named arguments if it were to be opt-in. Making it opt-in for avoiding any code deprecation is simply not worth it. The benefit of readability by the callee greatly outweighs the cost of the code deprecation. -Alex We have to take account of libraries that are rarely updated.
Feb 15 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite":- new function attribute is almost an automatic "no, thanks" from me - misordering arguments, I don't like it either
Feb 15 2019
On Friday, 15 February 2019 at 15:10:28 UTC, Guillaume Piolat wrote:- misordering arguments, I don't like it eitherYeah, that bothers me, too. OP: And how would a feature like this work with variable-length argument lists? As for the whole named arguments thing, I like the concept, but I'm still mulling over whether I connect with it in practice.
Jun 07 2019
I'd just like to point out to everyone that this thread is for the first round of DIP 1019's community review. Andrei appears to have reviewed the correct version of the DIP, he simply misplaced his feedback. The second round is going on here: https://forum.dlang.org/thread/sbkftyukevoydivapumm forum.dlang.org Best if we keep all the discussion in one place.
Jun 07 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite":Wee! Named arguments :D There's also another solution that was brought up by Simen. Forum post: https://forum.dlang.org/post/ejnsqqebrjbwefjhagvg forum.dlang.org An implementation: https://github.com/aliak00/ddash/commit/911e3b580e7bbe06f43c258a2d1c78f97a9668c5#diff-6919882fdb1af168f0e5b90603414fae Basically we have the following decision dimensions when allowing named parameters in APIs Also I'm on the side of named parameters being the default and the API author deciding if their use is opt-out. But, that's a compile time breaking change to, basically, everything. So I guess that's out the window. So, there's probably a better chance with named parameters being opt-in. 1) I don't think it should be re-orderable because it allows callers to abuse APIs and not be used how the author (may have) intended: void call(int me, int maybe) {} call(maybe: 3, me: 2); call(me: 2, maybe: 3); Carly Ray would roll in her grave :p Also, who's calling who?!? Also, it makes named overload resolution impossible should the need arise: void call(int a, int b) {} void call(int b, int a) {} call(a: 3, b: 4); // ?? 2) Then there's the issue of external names and internal names, as an API designer, I want to be able to specify an external name but also have a different internal identifier move(T)(T from, T to); Requires the awkward use of variables from and to in the function body. It's not the end of the world of course, but allowing external and internal variable naming gives allows for the best user experience, and code readability from both caller and API author: move(T)(T from source, T to dest) { // implementation use source and dest } // caller uses from and to: move(from: x, to: y); 3) Disallowing named arguments. In my experience this is especially useful for the first argument to a function. move(x, to: y); How does a ":" sound as an addition to the parameter list to be able to achieve all of these? By default, everything stays the same, i.e. no named parameters. If you add a ":" to your parameter then it *must* be called via named arguments by the caller. And if you have a second identifier after your first, then that one becomes the internal identifier (this can also be a separate DIP maybe in the future as it's additional) move(T)(T :from, T :to); move(a, b); // error move(from: a, to: b); // ok move(T)(T from, T :to); move(a, b); // error move(from: a, to: b); // error move(a, to: b); // ok Then there's the issue of default arguments: * A default argument on an unnamed parameter can only come at the end. * A default argument on a named parameter can go anywhere void func(int a = 3, int :b) func(b: 7); // ok void func(int a = 3, int b); // error void func(int :a = 7, int b, int :c = 4); func(3); // ok void func(int :a = 7, int b, int :c); func(3, c: 8); I think parameter lock in is as valid as a concern as function name lock in. Also, I agree with everything Paul Backus has said in his response :) I'm just not so sure how feasible it'd be to allow an API author to force named arguments on their APIs and at the same time allow callers to use current libraries by using named arguments? I didn't think about it too much. But maybe they work together seamlessly? Cheers, - Ali
Feb 15 2019
On Friday, 15 February 2019 at 17:03:40 UTC, aliak wrote:On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:Yes, one of my "design goal" is to maximize my chance :)This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite":Wee! Named arguments :D There's also another solution that was brought up by Simen. Forum post: https://forum.dlang.org/post/ejnsqqebrjbwefjhagvg forum.dlang.org An implementation: https://github.com/aliak00/ddash/commit/911e3b580e7bbe06f43c258a2d1c78f97a9668c5#diff-6919882fdb1af168f0e5b90603414fae Basically we have the following decision dimensions when allowing named parameters in APIs Also I'm on the side of named parameters being the default and the API author deciding if their use is opt-out. But, that's a compile time breaking change to, basically, everything. So I guess that's out the window. So, there's probably a better chance with named parameters being opt-in.1) I don't think it should be re-orderable because it allows callers to abuse APIs and not be used how the author (may have) intended: void call(int me, int maybe) {} call(maybe: 3, me: 2); call(me: 2, maybe: 3); Carly Ray would roll in her grave :p Also, who's calling who?!?I was reluctant about add reordering too. The first version of the proposal doesn't have reordering. But after some thought, I realized reordering cannot be add as an extension of this proposal without breakage. So in order to not rule reordering out, I have to include that in the proposal. But now I reconsider it again, it is probably not as bad as I thought. The future reordering proposal can probably *also* be opt-in behind a attribute. So I am not really decided at this moment.Also, it makes named overload resolution impossible should the need arise: void call(int a, int b) {} void call(int b, int a) {} call(a: 3, b: 4); // ??This is a compile time error since the call matches both functions.2) Then there's the issue of external names and internal names, as an API designer, I want to be able to specify an external name but also have a different internal identifier move(T)(T from, T to); Requires the awkward use of variables from and to in the function body. It's not the end of the world of course, but allowing external and internal variable naming gives allows for the best user experience, and code readability from both caller and API author: move(T)(T from source, T to dest) { // implementation use source and dest } // caller uses from and to: move(from: x, to: y);This can be done with this proposal, you do move(T)(T source, T dest) { /* code */ } named move(T)(T from, T to);3) Disallowing named arguments. In my experience this is especially useful for the first argument to a function. move(x, to: y); How does a ":" sound as an addition to the parameter list to be able to achieve all of these? By default, everything stays the same, i.e. no named parameters. If you add a ":" to your parameter then it *must* be called via named arguments by the caller. And if you have a second identifier after your first, then that one becomes the internal identifier (this can also be a separate DIP maybe in the future as it's additional) move(T)(T :from, T :to); move(a, b); // error move(from: a, to: b); // ok move(T)(T from, T :to); move(a, b); // error move(from: a, to: b); // error move(a, to: b); // ok Then there's the issue of default arguments: * A default argument on an unnamed parameter can only come at the end. * A default argument on a named parameter can go anywhere void func(int a = 3, int :b) func(b: 7); // ok void func(int a = 3, int b); // error void func(int :a = 7, int b, int :c = 4); func(3); // ok void func(int :a = 7, int b, int :c); func(3, c: 8); I think parameter lock in is as valid as a concern as function name lock in.This proposal doesn't prevent your suggestion from being implemented in the future :)[snip]
Feb 15 2019
On Friday, 15 February 2019 at 18:26:34 UTC, Yuxuan Shui wrote:Yes, one of my "design goal" is to maximize my chance :)Increasing the chance of this DIP being accepted by avoiding code deprecation shouldn't be any DIP design goal. We shouldn't reject good design just because it may break people code. That is THE ISSUE THAT I HAVE WITH THE C++ COMMITTEE! If I were so worried about breaking code when introducing new features I would use c++! Which guess what? The readability is horrible! So god awful! They are STILL stuck with using header files in spite of introducing modules! I can go on and on about this, but it be pointless, because they have such a religious devotion to backwards compatibility that I just gave up on them. D should not make the fatal mistake of "persevering backwards capability at all cost" scenario, that what c++ is for. Argue that the benefit of readability overweight the cost of breaking peoples code, which can be easily fix with the rename feature that comes with IDE and tools. Stand your ground. Please! I do not want to go around and beg package makers to label their functions named for readability sake! -Alex
Feb 15 2019
On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:On Friday, 15 February 2019 at 18:26:34 UTC, Yuxuan Shui wrote:It's actually worse than that--the purpose of named is not to avoid breaking *existing* code. Existing code that doesn't use named arguments will continue to work regardless. The purpose of named is to ensure that (a) changes to existing code which have yet to be made (b) do not break future code that has yet to be written.Yes, one of my "design goal" is to maximize my chance :)Increasing the chance of this DIP being accepted by avoiding code deprecation shouldn't be any DIP design goal. We shouldn't reject good design just because it may break people code. [...] D should not make the fatal mistake of "persevering backwards capability at all cost" scenario, that what c++ is for.
Feb 15 2019
On Friday, 15 February 2019 at 20:11:47 UTC, Paul Backus wrote:On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:simple find and replace tool in your favorite editor can simply fix the code breakage due to parameter name change. This should really be opt-out rather then opt-in, as parameter name changes are rare and easy to fix. I don't think library authors should be nagged by user to put the named attribute to their functions just so they can use Named Arguments! If the calle is so worried about their code break, because of the name change of the parameter, then they shouldn't be using name arguments at all! I don't want Named Arguments to be dead on arrival, as your favorite library hasn't updated their functions to use the named arguments feature. -AlexOn Friday, 15 February 2019 at 18:26:34 UTC, Yuxuan Shui wrote:It's actually worse than that--the purpose of named is not to avoid breaking *existing* code. Existing code that doesn't use named arguments will continue to work regardless. The purpose of named is to ensure that (a) changes to existing code which have yet to be made (b) do not break future code that has yet to be written.Yes, one of my "design goal" is to maximize my chance :)Increasing the chance of this DIP being accepted by avoiding code deprecation shouldn't be any DIP design goal. We shouldn't reject good design just because it may break people code. [...] D should not make the fatal mistake of "persevering backwards capability at all cost" scenario, that what c++ is for.
Feb 15 2019
On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:On Friday, 15 February 2019 at 18:26:34 UTC, Yuxuan Shui wrote:I am not saying "we should never break any code". I am deferring that decision to someone else. If someone want to make named parameters opt-out instead of opt-in, they can do so on top of this DIP. I am just not doing that in my proposal.Yes, one of my "design goal" is to maximize my chance :)Increasing the chance of this DIP being accepted by avoiding code deprecation shouldn't be any DIP design goal. We shouldn't reject good design just because it may break people code. That is THE ISSUE THAT I HAVE WITH THE C++ COMMITTEE! If I were so worried about breaking code when introducing new features I would use c++! Which guess what? The readability is horrible! So god awful! They are STILL stuck with using header files in spite of introducing modules! I can go on and on about this, but it be pointless, because they have such a religious devotion to backwards compatibility that I just gave up on them. D should not make the fatal mistake of "persevering backwards capability at all cost" scenario, that what c++ is for. Argue that the benefit of readability overweight the cost of breaking peoples code, which can be easily fix with the rename feature that comes with IDE and tools. Stand your ground. Please! I do not want to go around and beg package makers to label their functions named for readability sake! -Alex
Feb 15 2019
On Friday, 15 February 2019 at 20:35:14 UTC, Yuxuan Shui wrote:On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:Why? We need to get it right the first time, as a.)This is a slow process b.)Would require another 180+ days if A&W reject this.[...]I am not saying "we should never break any code". I am deferring that decision to someone else. If someone want to make named parameters opt-out instead of opt-in, they can do so on top of this DIP. I am just not doing that in my proposal.
Feb 15 2019
On Friday, 15 February 2019 at 20:51:35 UTC, 12345swordy wrote:On Friday, 15 February 2019 at 20:35:14 UTC, Yuxuan Shui wrote:You answered the why yourself:On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:Why?[...]I am not saying "we should never break any code". I am deferring that decision to someone else. If someone want to make named parameters opt-out instead of opt-in, they can do so on top of this DIP. I am just not doing that in my proposal.a.)This is a slow process b.)Would require another 180+ days if A&W reject this.So I don't want this proposal to be rejected.
Feb 15 2019
On Friday, 15 February 2019 at 21:19:14 UTC, Yuxuan Shui wrote:On Friday, 15 February 2019 at 20:51:35 UTC, 12345swordy wrote:There are severe usability disadvantages that outweigh readability advantages if this were to be opt-in. The decision to used named arguments should rest on the calle not the caller. When the calle used named arguments they are opt-in the risk of their code breakage in which forcing the caller to mark their function named does NOT solve this. Here is my statement: The caller is NOT AND SHOULD NOT BE responsible for code breakage when they renamed parameters as the Named Arguments are opt-in from the client side of the code. Forcing the Caller to be responsible for Named Arguments, is a HUGE usability disadvantage as it requires many existing libraries out there to mark their functions named if the client wants to use named arguments, when they have already have other attributes to worry about. It even worst for library creators to mark named in their modules EVERY SINGLE TIME if they to grant the client access to named arguments. Function not having Named Arguments support should be RARE NOT COMMON! This poor design should be the basis of this being rejected.On Friday, 15 February 2019 at 20:35:14 UTC, Yuxuan Shui wrote:You answered the why yourself:On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:Why?[...]I am not saying "we should never break any code". I am deferring that decision to someone else. If someone want to make named parameters opt-out instead of opt-in, they can do so on top of this DIP. I am just not doing that in my proposal.a.)This is a slow process b.)Would require another 180+ days if A&W reject this.So I don't want this proposal to be rejected.
Feb 15 2019
On Friday, 15 February 2019 at 20:35:14 UTC, Yuxuan Shui wrote:I am not saying "we should never break any code". I am deferring that decision to someone else. If someone want to make named parameters opt-out instead of opt-in, they can do so on top of this DIP. I am just not doing that in my proposal.I think that, at least, you should include more details in the DIP text about what kind of breakage the named attribute would prevent, how these breakages would otherwise occur, and what kind of situation would lead to them. I personally think breakages are unlikely: - The maintainer needs to export functions with argument names. - The user has to explicitly use DIP-1019 and use named arguments. - The maintainer has to change the argument names, without being aware of DIP-1019 and using your forward declaration workaround (and without being made aware of it by subsequent issues). - Then the user gets an easy-to-fix compile error when they update their library. In these cases, the user can always avoid using named arguments if there's a significant risk that named breakage occurs (eg if the library was written before DIP-1019). Keep in mind that library maintainers can always opt out of named arguments by exporting prototypes with anonymous arguments: int foobar(int, float, string); All-in-all, it's a trade-off with downsides either way, but I think being able to use named argument with any library made at any time far outweighs the breakage risks.
Feb 16 2019
On Sunday, 17 February 2019 at 00:38:33 UTC, Olivier FAURE wrote:On Friday, 15 February 2019 at 20:35:14 UTC, Yuxuan Shui wrote:I forgot to say, thank you for your work on this DIP, and for your upbeat attitude in discussing possible improvements :)I am not saying "we should never break any code". I am deferring that decision to someone else. If someone want to make named parameters opt-out instead of opt-in, they can do so on top of this DIP. I am just not doing that in my proposal.
Feb 16 2019
On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:... D should not make the fatal mistake of "persevering backwards capability at all cost" scenario, that what c++ is for. ...I agree with this and despite breaking code indeed sucks, for a language like D which has a very small user base, I think it should go for it instead of adding new properties for handling different cases and trying to be like C++. In fact look for example C++ 17 or 20 and you can clearly see that they are trying hard to force people over new features/ways of programming and hoping the old "habits" go way. Ron.
Feb 15 2019
On Friday, 15 February 2019 at 22:17:28 UTC, Ron J wrote:On Friday, 15 February 2019 at 19:11:55 UTC, 12345swordy wrote:The "Old Way" aka C++98 will still be used simply because they still support it. If they are serious about preventing people from coding the "Old Way" then they simply need to stop supporting the "Old Way". Until then the dinosaurs will still type C++98 code. -Alex... D should not make the fatal mistake of "persevering backwards capability at all cost" scenario, that what c++ is for. ...I agree with this and despite breaking code indeed sucks, for a language like D which has a very small user base, I think it should go for it instead of adding new properties for handling different cases and trying to be like C++. In fact look for example C++ 17 or 20 and you can clearly see that they are trying hard to force people over new features/ways of programming and hoping the old "habits" go way. Ron.
Feb 15 2019
On Friday, 15 February 2019 at 18:26:34 UTC, Yuxuan Shui wrote:On Friday, 15 February 2019 at 17:03:40 UTC, aliak wrote:Yeah, I understand that. Though, just for the record if it came down to a vote, I'd 100% vote for a deprecation path towards named-parameters-by-default.On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:Yes, one of my "design goal" is to maximize my chance :)This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite":Wee! Named arguments :D There's also another solution that was brought up by Simen. Forum post: https://forum.dlang.org/post/ejnsqqebrjbwefjhagvg forum.dlang.org An implementation: https://github.com/aliak00/ddash/commit/911e3b580e7bbe06f43c258a2d1c78f97a9668c5#diff-6919882fdb1af168f0e5b90603414fae Basically we have the following decision dimensions when allowing named parameters in APIs Also I'm on the side of named parameters being the default and the API author deciding if their use is opt-out. But, that's a compile time breaking change to, basically, everything. So I guess that's out the window. So, there's probably a better chance with named parameters being opt-in.Yeah, it may also make it simpler? As in, without reordering the resolution order of parameters don't have to be changed. But with, then you need to account for that too maybe. Also one more advantage, the call-site is consistent at every usage. Allowing reordering encourages sloppiness on the caller, with no particular (at least that I can see) benefit.1) I don't think it should be re-orderable because it allows callers to abuse APIs and not be used how the author (may have) intended: void call(int me, int maybe) {} call(maybe: 3, me: 2); call(me: 2, maybe: 3); Carly Ray would roll in her grave :p Also, who's calling who?!?I was reluctant about add reordering too. The first version of the proposal doesn't have reordering. But after some thought, I realized reordering cannot be add as an extension of this proposal without breakage. So in order to not rule reordering out, I have to include that in the proposal. But now I reconsider it again, it is probably not as bad as I thought. The future reordering proposal can probably *also* be opt-in behind a attribute. So I am not really decided at this moment.But this can be resolved if there was no reordering and "call" was a function that "required" named arguments. Or did I miss something?Also, it makes named overload resolution impossible should the need arise: void call(int a, int b) {} void call(int b, int a) {} call(a: 3, b: 4); // ??This is a compile time error since the call matches both functions.Ah, ok, I did not catch that was possible. Cool, that could work as well. Requires more typing and maintenance of function signatures perhaps, which may be harder to deal with then just allowing that kind of functionality in one function signature.2) Then there's the issue of external names and internal names, as an API designer, I want to be able to specify an external name but also have a different internal identifier move(T)(T from, T to); Requires the awkward use of variables from and to in the function body. It's not the end of the world of course, but allowing external and internal variable naming gives allows for the best user experience, and code readability from both caller and API author: move(T)(T from source, T to dest) { // implementation use source and dest } // caller uses from and to: move(from: x, to: y);This can be done with this proposal, you do move(T)(T source, T dest) { /* code */ } named move(T)(T from, T to);This proposal doesn't prevent your suggestion from being implemented in the future :)True, but if we force named parameters across the whole function now with something like named, then what will add a second way to have named parameters whereas it can potentially just be tackled in one go now. So maybe better to just allow that now? Also ":" is symmetrical with the way you call a named argument as well. Thought it would just be a bit nicer than taking up a new attribute, which is also quite generically "named".One thing that could be mentioned in the DIP is the ability to allow for function overloads that were previously impossible: Consider: // Function to load a value from a program option auto createProgramOption(T)(string name, string envVar = null, T defaultValue = T.init); I want to force "name" but optionally have a defaultValue and an envVar. What happens if T is a string? How do you make the call-site nice? createProgramOption!int("port", "PORT", 8080); // ok createProgramOption!string("host", "HOST", "localhost"); // ok // Now I want to allow these two: createProgramOption!string("host","localhost"); // defaultValue version createProgramOption!string("host","HOST"); // envVar version What do I do? How do I achieve this without named arguments? With named arguments: auto createProgramOption(T)(string name, string envVar = null, T defaultValue = T.init); createProgramOption!string(name: "host", defaultValue: "localhost"); createProgramOption!string(name: "host", envVar: "HOST"); // Just works, intuitive, obvious, readable[snip]
Feb 16 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite":I think the "Completeness" section contains some arguable points. The proposed solution doesn't take into account the cases where you need to partially skip default arguments. Say, we have a function: ```void drawCircle(int x, int y, int radius, Border border = Border.Solid, Bg bg = Bg.Transparent)``` Then we want to call this function with default parameters except the background (bg). The best way to do that would be: ```drawCircle(10, 10, 5, bg: Bg.Red);``` So you see that we omitted the "border" parameter. However, the proposed solution forces us to do that: ```drawCircle(x: 10, y: 10, radius: 5, bg: Bg.Red);``` A lot more unnecessary typing. Python, for example, allows us to mix both named and unnamed arguments, and thus effectively skip the default ones.
Feb 15 2019
On Friday, 15 February 2019 at 17:06:18 UTC, Jacob Shtokolov wrote:On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This proposal is written purposefully to minimized its scope. Yes, the current proposal doesn't address this use case, but it doesn't prevent future DIPs from doing so.[...]I think the "Completeness" section contains some arguable points. The proposed solution doesn't take into account the cases where you need to partially skip default arguments. Say, we have a function: ```void drawCircle(int x, int y, int radius, Border border = Border.Solid, Bg bg = Bg.Transparent)``` Then we want to call this function with default parameters except the background (bg). The best way to do that would be: ```drawCircle(10, 10, 5, bg: Bg.Red);``` So you see that we omitted the "border" parameter. However, the proposed solution forces us to do that: ```drawCircle(x: 10, y: 10, radius: 5, bg: Bg.Red);``` A lot more unnecessary typing. Python, for example, allows us to mix both named and unnamed arguments, and thus effectively skip the default ones.
Feb 15 2019
Am 15.02.19 um 13:56 schrieb Mike Parker:[...]All in all, DIP 1019 looks quite interesting and also primising to me. I do however see some issues with the DIP: 1. The rationale describes 2 problems that can arise when not having named arguments, but it does not describe how those problems could be prevented by using named arguments. 2. In the "Description" secion, the DIP says:When the label and the corresponding parameter name mismatch, thecompiler will generate an error of the following nature: "Named argument 'foo' does not match function parameter name 'bar'." I don't really understand how the compiler should generate this exact error message. How can the compiler know that the argument passed with name 'foo' is supposed to match the actual parameter 'bar'? I don't think this is possible if reordering of named arguments is allowed (as the DIP later suggests). To clearify this, the DIP should provide code examples where those mismatches occur and what errors are detected (or not bother with specifying what the exact error message is, but simply state that this is a compile error, but also provide examples). 3. In the completeness section, I would have liked an example to make this more easily understandable. 4. In the "Alternatives" section, the DIP says:For example, in one potential library-only solution, it is necessaryto call functions like so:args!(add, a=>1, b=>1); This has too much noise and, moreover, does not allow for the use ofUniform Function Call Syntax (UFCS). This clearly suggests that named arguments as proposed by the DIP should work with UFCS. However, the DIP fails to explain how this should actually work. At the moment, UFCS works by lowering as described in the following example: ```d int add(int a, int b, int c) { /* ... */ } void main() { 1.add(2, 3); // lowered to add(1, 2, 3); } ``` It is totally unclear how this should work with named arguments. 5. Similarly, as already mentioned by somebody else, the DIP fails to explain interaction with function default arguments. 6. Another possible interaction the DIP does not mention at all is implicit istanciation of template functions. Without giving it too much tought, to me it looks like this should actually work. But the DIP does not consider this at all. It should at least describe whether those features are compatible or not, and provide examples if they are.
Feb 15 2019
On Friday, 15 February 2019 at 18:04:36 UTC, Johannes Loher wrote:Am 15.02.19 um 13:56 schrieb Mike Parker:Thanks for pointing these out, they will be fixed in the next revision.[...]All in all, DIP 1019 looks quite interesting and also primising to me. I do however see some issues with the DIP: 1. The rationale describes 2 problems that can arise when not having named arguments, but it does not describe how those problems could be prevented by using named arguments. 2. In the "Description" secion, the DIP says:When the label and the corresponding parameter name mismatch, thecompiler will generate an error of the following nature: "Named argument 'foo' does not match function parameter name 'bar'." I don't really understand how the compiler should generate this exact error message. How can the compiler know that the argument passed with name 'foo' is supposed to match the actual parameter 'bar'? I don't think this is possible if reordering of named arguments is allowed (as the DIP later suggests). To clearify this, the DIP should provide code examples where those mismatches occur and what errors are detected (or not bother with specifying what the exact error message is, but simply state that this is a compile error, but also provide examples). 3. In the completeness section, I would have liked an example to make this more easily understandable. 4. In the "Alternatives" section, the DIP says:For example, in one potential library-only solution, it is necessaryto call functions like so:args!(add, a=>1, b=>1); This has too much noise and, moreover, does not allow for the use ofUniform Function Call Syntax (UFCS). This clearly suggests that named arguments as proposed by the DIP should work with UFCS. However, the DIP fails to explain how this should actually work. At the moment, UFCS works by lowering as described in the following example: ```d int add(int a, int b, int c) { /* ... */ } void main() { 1.add(2, 3); // lowered to add(1, 2, 3); } ``` It is totally unclear how this should work with named arguments.5. Similarly, as already mentioned by somebody else, the DIP fails to explain interaction with function default arguments.I think it is reasonable to require a prefix of the parameters are specified. e.g. int fun(int a, int b = 1, int c = 2, int d = 3); The user can specify (a), (a, b), (a, b, c) or all of the parameters, and the arguments can be in any order.6. Another possible interaction the DIP does not mention at all is implicit instantiation of template functions. Without giving it too much thought, to me it looks like this should actually work. But the DIP does not consider this at all. It should at least describe whether those features are compatible or not, and provide examples if they are.I think it should just work. But I would give it some thought and include that in the next revision. Thanks!
Feb 15 2019
On Friday, 15 February 2019 at 18:32:52 UTC, Yuxuan Shui wrote:In my experience, one of the greatest benefits of argument re-ordering is that it lets you leave out optional arguments at the call site. For example, in Python, if you wanted to use the default value for every argument except `d`, you could write this: fun(a=123, d=456) ...whereas with this proposal, you'd be required to needlessly repeat the default values for `a` and `b`: fun(a: 123, d: 456, b: 1, c: 2); If this DIP isn't going to allow leaving out optional arguments in all cases, it might be better to simply forbid argument re-ordering entirely (or at least, to leave the issue for a future DIP).5. Similarly, as already mentioned by somebody else, the DIP fails to explain interaction with function default arguments.I think it is reasonable to require a prefix of the parameters are specified. e.g. int fun(int a, int b = 1, int c = 2, int d = 3); The user can specify (a), (a, b), (a, b, c) or all of the parameters, and the arguments can be in any order.
Feb 15 2019
On Friday, 15 February 2019 at 20:28:02 UTC, Paul Backus wrote:On Friday, 15 February 2019 at 18:32:52 UTC, Yuxuan Shui wrote:Being able to leave out arguments would be hugely beneficial to the caller. You don't need reordering to achieve that though, the arguments can still be specified in the correct order while the ones with default values are left out: https://swift.godbolt.org/z/VhtoufIn my experience, one of the greatest benefits of argument re-ordering is that it lets you leave out optional arguments at the call site. For example, in Python, if you wanted to use the default value for every argument except `d`, you could write this: fun(a=123, d=456) ...whereas with this proposal, you'd be required to needlessly repeat the default values for `a` and `b`: fun(a: 123, d: 456, b: 1, c: 2); If this DIP isn't going to allow leaving out optional arguments in all cases, it might be better to simply forbid argument re-ordering entirely (or at least, to leave the issue for a future DIP).5. Similarly, as already mentioned by somebody else, the DIP fails to explain interaction with function default arguments.I think it is reasonable to require a prefix of the parameters are specified. e.g. int fun(int a, int b = 1, int c = 2, int d = 3); The user can specify (a), (a, b), (a, b, c) or all of the parameters, and the arguments can be in any order.
Feb 16 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment by the language maintainers. Please familiarize yourself with the documentation for the Community Review before participating. https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review Thanks in advance to all who participate.As another alternative, named parameters can be implemented using Tuple/tuple from the Phobos Library. This alternative solution will prevent silent breakage. The caller can not opt-out. This solution adds even more noise to function calls but typedef can reduce the noise. This solution does not address reordering but can be combined with other solutions that allow for reordering. Here is an example: import std.typecons; double get_area(Tuple!(double, "radius") t_radius) { double radius = t_radius.radius; return 3.14 * radius * radius; } double get_area(Tuple!(double, "diameter") t_diameter) { double radius = t_diameter.diameter / 2; return 3.14 * radius * radius; } void main() { import std.stdio; auto area = get_area(tuple!"radius"(4.)); writeln("Area with radius: ", area); area = get_area(tuple!"diameter"(8.)); writeln("Area with diameter: ", area); }
Feb 15 2019
On Friday, 15 February 2019 at 21:05:38 UTC, Golden Rockefeller wrote:On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:The downside to your solution is an increases in memory.This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment by the language maintainers. Please familiarize yourself with the documentation for the Community Review before participating. https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review Thanks in advance to all who participate.As another alternative, named parameters can be implemented using Tuple/tuple from the Phobos Library. This alternative solution will prevent silent breakage. The caller can not opt-out. This solution adds even more noise to function calls but typedef can reduce the noise. This solution does not address reordering but can be combined with other solutions that allow for reordering. Here is an example: import std.typecons; double get_area(Tuple!(double, "radius") t_radius) { double radius = t_radius.radius; return 3.14 * radius * radius; } double get_area(Tuple!(double, "diameter") t_diameter) { double radius = t_diameter.diameter / 2; return 3.14 * radius * radius; } void main() { import std.stdio; auto area = get_area(tuple!"radius"(4.)); writeln("Area with radius: ", area); area = get_area(tuple!"diameter"(8.)); writeln("Area with diameter: ", area); }
Feb 15 2019
On Friday, 15 February 2019 at 21:05:38 UTC, Golden Rockefeller wrote:As another alternative, named parameters can be implemented using Tuple/tuple from the Phobos Library.Tuples exist as an internal compiler type. The thing is just that there's no syntax for it. So what you think is a library thing is actually mostly compiler one. Maybe the tuple DIP should be handled before the named parameter one maybe ?
Feb 16 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment by the language maintainers. Please familiarize yourself with the documentation for the Community Review before participating. https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review Thanks in advance to all who participate.drawRect(x: 0, y: 0, width: 1, height: 1); drawRect(width: 1, height: 1, x: 0, y: 0); The DIP doesn't state what order these are executed in. The spec states parameters are executed left to right. When you can rearrange the function arguments at the call site, is it going to call left to right as it is orangized at the call site, or left to right as according to as the function definition? I don't think we should require an attribute for this either. We already have enough we don't need one more. It means we can't use it for instances where you want to change a default value but keep other options at their default much like void foo( int bar, int someDefault = 0, int someOtherDefault = 1 ); foo( 10, someOtherDefault: 2 );
Feb 15 2019
On Friday, 15 February 2019 at 22:48:52 UTC, Rubn wrote:On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:Good point. I will fix this in next revision. Thanks.[...]drawRect(x: 0, y: 0, width: 1, height: 1); drawRect(width: 1, height: 1, x: 0, y: 0); The DIP doesn't state what order these are executed in. The spec states parameters are executed left to right. When you can rearrange the function arguments at the call site, is it going to call left to right as it is orangized at the call site, or left to right as according to as the function definition?
Feb 16 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment by the language maintainers. Please familiarize yourself with the documentation for the Community Review before participating. https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review Thanks in advance to all who participate.With the struct initialization DIP there will come also named arguments complicity. https://github.com/wilzbach/DIPs/blob/b1283b455b635d7dcbc2c871d2aa47cc67190059/DIPs/DIP1xxx-sw.md Yes, the callee has to provide method/function overload with a structure containing all arguments. But in theory Phobos could provide a mixin/template to make this task a one liner. In my opinion this fits much nicer than introducing a new attribute. Kind regards Andre
Feb 16 2019
On Saturday, 16 February 2019 at 12:41:01 UTC, Andre Pany wrote:With the struct initialization DIP there will come also named arguments complicity. https://github.com/wilzbach/DIPs/blob/b1283b455b635d7dcbc2c871d2aa47cc67190059/DIPs/DIP1xxx-sw.md Yes, the callee has to provide method/function overload with a structure containing all arguments. But in theory Phobos could provide a mixin/template to make this task a one liner. In my opinion this fits much nicer than introducing a new attribute. Kind regards AndreI 100% support that. Relying on struct initialization is both the easiest and safest way to go in my opinion: 0) as a reminder the idea is that today you can do that: struct S { int a, int b=42 } void f(S args); S args = { .b=43 }; // yeah, useful C legacy! f(args); but there's currently no way to directly initialize that struct in the f() call. 1) it's already there. All problems have already been solved, the code is there with reordering, default values, order of evaluation etc. Struct initialization already works, just not in-place. 2) it's as backward compatible as it can be: as long as the calle provides a function that takes a struct as argument it'll work. It'll work with C code, it'll work with C++ code, it'll work without named, it'll just work. It's just structs, cleverly used. 3) the only thing needed is to finally close that in-place struct initialization DIP. I'd much rather have that than introducing new attributes and duplicating code (since, as I said, such code is already existing for partial structs initialization).
Feb 17 2019
On Sunday, 17 February 2019 at 13:44:09 UTC, Cym13 wrote:S args = { .b=43 }; // yeah, useful C legacy!I obviously meant: S args = { b: 43 };
Feb 17 2019
On Sunday, 17 February 2019 at 13:44:09 UTC, Cym13 wrote:On Saturday, 16 February 2019 at 12:41:01 UTC, Andre Pany wrote:Sure, but it has the exactly same property as named: it's opt-in. Yes, maybe you can do it with a one-liner (I don't know how. There doesn't seem to be a way to retrieve parameter names from a function), but that can't be easier than adding " named".[...]I 100% support that. Relying on struct initialization is both the easiest and safest way to go in my opinion: 0) as a reminder the idea is that today you can do that: struct S { int a, int b=42 } void f(S args); S args = { .b=43 }; // yeah, useful C legacy! f(args); but there's currently no way to directly initialize that struct in the f() call. 1) it's already there. All problems have already been solved, the code is there with reordering, default values, order of evaluation etc. Struct initialization already works, just not in-place. 2) it's as backward compatible as it can be: as long as the calle provides a function that takes a struct as argument it'll work. It'll work with C code, it'll work with C++ code, it'll work without named, it'll just work. It's just structs, cleverly used.3) the only thing needed is to finally close that in-place struct initialization DIP. I'd much rather have that than introducing new attributes and duplicating code (since, as I said, such code is already existing for partial structs initialization).So it probably could be reused?
Feb 17 2019
On Sunday, 17 February 2019 at 17:14:57 UTC, Yuxuan Shui wrote:On Sunday, 17 February 2019 at 13:44:09 UTC, Cym13 wrote:It already exists std.traits: ParameterIdentifierTuple Kind regards Andre[...]Sure, but it has the exactly same property as named: it's opt-in. Yes, maybe you can do it with a one-liner (I don't know how. There doesn't seem to be a way to retrieve parameter names from a function), but that can't be easier than adding " named".[...]So it probably could be reused?
Feb 17 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.mdwish list. It allows drastically improving the readability of code in many situations. With it, we can also do away with the awful Flag!"enableSomething" enableSomething / Yes.enableSomething templates. So, thank you for working on this.For example, in one potential library-only solution, it is necessary to call functions like so:args!(add, a=>1, b=>1);There is another big problem with this approach: you cannot do a=>a, b=>b etc. The compiler will pick up the fake lambda parameter instead of the variable from the outer scope. This is a pain because you will very often see fun(foo=foo, bar=bar) in idiomatic Python code.Opt-in: Calling a function with named arguments is opt-in on the callee side.named is not the best idea. I don't want to have to check every time if the library author remembered to slap named on the function I want to use named arguments with. Making it opt-in will probably mean that there will be people who use it and those who don't, and libraries written by users who don't will just cause frustration by those who do; and, for people who do, they might as well just slap it on everything, further contributing to attribute bloat. Also, the decision to use named arguments depends as much on the function as on the call site (e.g. how important is code readability vs. terseness in that particular piece of code). I'd be just too tempted to patch the compiler to enable it for everything. Generally, I do not buy the lock-in arguments, now or 10 years ago when Don shut the idea down the first time. I think it is enough to give library authors a way to provide aliases to old parameter names, so they have freedom to rename the parameters without breaking code using named arguments. I'm not sure if forward arguments is the best approach for this, seems very brittle - you don't update all signatures correctly, and suddenly some users of your library get hit with linking errors. And, what about templated functions? I think allowing alias in parameter lists would be worthwhile, e.g.: void drawRect(int x, int y, int width, int height, alias w = width, alias h = height); Bonus if "deprecated alias" is allowed and works as expected. Sorry, I'm jumping late into the discussion, so the above might have been already discussed.
Feb 16 2019
On Saturday, 16 February 2019 at 23:56:45 UTC, Vladimir Panteleev wrote:On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:Good point.This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.mdpersonal wish list. It allows drastically improving the readability of code in many situations. With it, we can also do away with the awful Flag!"enableSomething" enableSomething / Yes.enableSomething templates. So, thank you for working on this.For example, in one potential library-only solution, it is necessary to call functions like so:args!(add, a=>1, b=>1);There is another big problem with this approach: you cannot do a=>a, b=>b etc. The compiler will pick up the fake lambda parameter instead of the variable from the outer scope. This is a pain because you will very often see fun(foo=foo, bar=bar) in idiomatic Python code.It's not my favorite either. But I feel it is the best we can do at the moment.Opt-in: Calling a function with named arguments is opt-in on the callee side.named is not the best idea. I don't want to have to check every time if the library author remembered to slap named on the function I want to use named arguments with. Making it opt-in will probably mean that there will be people who use it and those who don't, and libraries written by users who don't will just cause frustration by those who do; and, for people who do, they might as well just slap it on everything, further contributing to attribute bloat. Also, the decision to use named arguments depends as much on the function as on the call site (e.g. how important is code readability vs. terseness in that particular piece of code). I'd be just too tempted to patch the compiler to enable it for everything.Generally, I do not buy the lock-in arguments, now or 10 years ago when Don shut the idea down the first time. I think it is enough to give library authors a way to provide aliases to old parameter names, so they have freedom to rename the parameters without breaking code using named arguments. I'm not sure if forward arguments is the best approach for this, seems very brittle - you don't update all signatures correctly, and suddenly some users of your library get hit with linking errors. And, what about templated functions?I don't see why forward declaration won't work for templated functions. And I don't quite understand why there might be linking problems. Can you give an example?I think allowing alias in parameter lists would be worthwhile, e.g.: void drawRect(int x, int y, int width, int height, alias w = width, alias h = height);So, there are a couple (two) problems with this: 1. the parameter list might just get longer and longer, making the documentation verbose and hard to read. 2. The user can use any combinations of the aliases (e.g. (x, y, w, height), (x, y, width, h) are all valid), this is not necessarily helpful to readability.Bonus if "deprecated alias" is allowed and works as expected.deprecated forward declaration could work. I will make that explicit in the next revision of this DIP.Sorry, I'm jumping late into the discussion, so the above might have been already discussed.You raised good points, thanks.
Feb 16 2019
On Sunday, 17 February 2019 at 00:27:42 UTC, Yuxuan Shui wrote:It's not my favorite either. But I feel it is the best we can do at the moment.Sorry, but I will vote against a DIP with named. With no guarantee that the opt-in will ever become opt-out or always available, the feature IMO will not carry its weight due to the problems I mentioned.I don't see why forward declaration won't work for templated functions.Will you need to expand the implicit template declaration (R fun(A)(A a){} => template fun(A) { R fun(A a) {} })? Or will the compiler need to detect that templates are part of the overload? I would suggest to consult with a DMD frontend expert to make sure the DIP is not overly difficult to implement.And I don't quite understand why there might be linking problems. Can you give an example?named: int add(int a, int b) { ... } int add(int c, int d); Let's say you want to add an optional argument to add. named: int add(int a, int b, int c = 0) { ... } but you forget to update the other forward declaration to match. You will not get a compiler error. You will not get a linking error if you never used the second declaration. But, a user using your library will now get a linking error if their code used the other declaration. I realized another problem after I sent my post: This approach is not usable for interface methods, and abstract methods (which may or may not have a body).
Feb 17 2019
On Sunday, 17 February 2019 at 00:27:42 UTC, Yuxuan Shui wrote:I'd say enabling named parameters for everything would be better than any benefits you get with using an attribute. named void foo(int a, int b); named void foo(int c, int d); I don't find the above situation all that useful. There are multiple ways to deal with this. Using another type for the parameters: void foo( Size ab ); void foo( Point cd ); Or simply give the functions a different name to distinguish between them. Allowing two functions to exist with the same type signature just adds unnecessary complexity. Looking at a few languages that support named parameters they Python. def abc(a, b): print( "ab", a, b) def abc(c, d): print( "cd", c, d) abc(c=10, d=20) first If you want this functionality you are probably going to have to make a more concrete case for it than what is currently in the DIP. If there are any languages that implement it the way you want to implement it it would probably be a good idea to include them as examples.It's not my favorite either. But I feel it is the best we can do at the moment.Opt-in: Calling a function with named arguments is opt-in on the callee side.named is not the best idea. I don't want to have to check every time if the library author remembered to slap named on the function I want to use named arguments with. Making it opt-in will probably mean that there will be people who use it and those who don't, and libraries written by users who don't will just cause frustration by those who do; and, for people who do, they might as well just slap it on everything, further contributing to attribute bloat. Also, the decision to use named arguments depends as much on the function as on the call site (e.g. how important is code readability vs. terseness in that particular piece of code). I'd be just too tempted to patch the compiler to enable it for everything.
Feb 17 2019
On Sunday, 17 February 2019 at 13:12:11 UTC, Rubn wrote:I'd say enabling named parameters for everything would be better than any benefits you get with using an attribute. named void foo(int a, int b); named void foo(int c, int d); I don't find the above situation all that useful. There are multiple ways to deal with this. Using another type for the parameters: void foo( Size ab ); void foo( Point cd ); Or simply give the functions a different name to distinguish between them. Allowing two functions to exist with the same type signature just adds unnecessary complexity.This is allowed, _right now_. This is not an addition made by this DIP. Example: https://d.godbolt.org/z/hbwsaULooking at a few languages that support named parameters they and Python. def abc(a, b): print( "ab", a, b) def abc(c, d): print( "cd", c, d) abc(c=10, d=20) the firstAnd they have the problem that the name of the parameter becomes part of the API. This is something this DIP tries to solve.If you want this functionality you are probably going to have to make a more concrete case for it than what is currently in the DIP. If there are any languages that implement it the way you want to implement it it would probably be a good idea to include them as examples.I am pretty sure this DIP listed some major languages with this feature, and it also includes concrete examples.
Feb 17 2019
On Sunday, 17 February 2019 at 17:09:57 UTC, Yuxuan Shui wrote:And they have the problem that the name of the parameter becomes part of the API. This is something this DIP tries to solve.A better solution would be allowing nameless parameters functions and refer the parameters by index. -Alex
Feb 17 2019
On Sunday, 17 February 2019 at 17:48:33 UTC, 12345swordy wrote:On Sunday, 17 February 2019 at 17:09:57 UTC, Yuxuan Shui wrote:This possibility exists already via variadic templates and via ´´´ void main() { fun(4, "kuku"); } void fun(int, string) { import std.stdio; writeln(_param_0); writeln(_param_1); } ´´´And they have the problem that the name of the parameter becomes part of the API. This is something this DIP tries to solve.A better solution would be allowing nameless parameters functions and refer the parameters by index. -Alex
Feb 17 2019
On Sunday, 17 February 2019 at 17:48:33 UTC, 12345swordy wrote:On Sunday, 17 February 2019 at 17:09:57 UTC, Yuxuan Shui wrote:That'd be worse, it'd make code less readable, the opposite of what named parameters are for.And they have the problem that the name of the parameter becomes part of the API. This is something this DIP tries to solve.A better solution would be allowing nameless parameters functions and refer the parameters by index. -Alex
Feb 17 2019
On Sunday, 17 February 2019 at 18:00:46 UTC, Rubn wrote:On Sunday, 17 February 2019 at 17:48:33 UTC, 12345swordy wrote:That is only if you are so worried about "parameter name becomes part of the API", which such concerns should be the exception, community that worry about named parameter becomes part of the API, when named parameters are introduced. Client can simply use find and replace if the library they using change their parameter name. It is not a deal breaker as the DIP making out to be. Regardless, my objections still stand regarding named attribute and I can not tell other people with a straight face that in order to use named parameters they have to use named attribute without expecting them to look at me like "Are you insane?" I do not want D design to be worst, because of the "avoiding breaking code at all cost" mentality. That is what C++ is for.On Sunday, 17 February 2019 at 17:09:57 UTC, Yuxuan Shui wrote:That'd be worse, it'd make code less readable, the opposite of what named parameters are for.And they have the problem that the name of the parameter becomes part of the API. This is something this DIP tries to solve.A better solution would be allowing nameless parameters functions and refer the parameters by index. -Alex
Feb 17 2019
On Sunday, 17 February 2019 at 18:57:26 UTC, 12345swordy wrote:Regardless, my objections still stand regarding named attribute and I can not tell other people with a straight face that in order to use named parameters they have to use named attribute without expecting them to look at me like "Are you insane?" I do not want D design to be worst, because of the "avoiding breaking code at all cost" mentality. That is what C++ is for.While I still think named attribute feels weird, I know at least one language that requires opt-in for named arguments: Dart. An example is here: https://stackoverflow.com/a/13264231 . In Dart, you can mark arguments as named: getHttpUrl(String server, String path, {int port: 80}) and then call it: getHttpUrl('example.com', '/index.html', port: 8080); and you MUST use the name if it's a named argument. Also, mixing optional arguments and named arguments is just not allowed, so it solves the issue of how to deal with such ambiguous cases: thisFunctionWontWork(String foo, [String positonal], {String named})
Feb 17 2019
On Sunday, 17 February 2019 at 19:52:14 UTC, JN wrote:On Sunday, 17 February 2019 at 18:57:26 UTC, 12345swordy wrote:Even though that is interesting, what is being currently presented is optional and not a requirement when the user call functions that are marked Named. That quite different from Dart. -AlexRegardless, my objections still stand regarding named attribute and I can not tell other people with a straight face that in order to use named parameters they have to use named attribute without expecting them to look at me like "Are you insane?" I do not want D design to be worst, because of the "avoiding breaking code at all cost" mentality. That is what C++ is for.While I still think named attribute feels weird, I know at least one language that requires opt-in for named arguments: Dart. An example is here: https://stackoverflow.com/a/13264231 . In Dart, you can mark arguments as named: getHttpUrl(String server, String path, {int port: 80}) and then call it: getHttpUrl('example.com', '/index.html', port: 8080); and you MUST use the name if it's a named argument. Also, mixing optional arguments and named arguments is just not allowed, so it solves the issue of how to deal with such ambiguous cases: thisFunctionWontWork(String foo, [String positonal], {String named})
Feb 17 2019
On Sunday, 17 February 2019 at 17:09:57 UTC, Yuxuan Shui wrote:On Sunday, 17 February 2019 at 13:12:11 UTC, Rubn wrote:Yes that's very different from what you want to implement it. See below.I'd say enabling named parameters for everything would be better than any benefits you get with using an attribute. named void foo(int a, int b); named void foo(int c, int d); I don't find the above situation all that useful. There are multiple ways to deal with this. Using another type for the parameters: void foo( Size ab ); void foo( Point cd ); Or simply give the functions a different name to distinguish between them. Allowing two functions to exist with the same type signature just adds unnecessary complexity.This is allowed, _right now_. This is not an addition made by this DIP. Example: https://d.godbolt.org/z/hbwsaUYes and Python doesn't behave the way you are suggesting. Listing the languages that implement the feature but not how they implement it makes the argument weaker. You list Python but I would not say Python implements this feature the same way as you are suggesting it to be implemented. I'd use Python as an example against this DIP (as I have). Eg the DIP suggests this be valid code so long as it can be distinguished by at least one parameter. named: int add(int a, int b) { ... } int add(int c, int d) { ... } If you try and do the following currently: int add(int a, int b) { ... } int add(int c, int d) { ... } // error You get a compiler error. Defining two functions with the same type signatures shouldn't be possible, with or without named parameters. It just adds un-needed complexity.Looking at a few languages that support named parameters they and Python. def abc(a, b): print( "ab", a, b) def abc(c, d): print( "cd", c, d) abc(c=10, d=20) the firstAnd they have the problem that the name of the parameter becomes part of the API. This is something this DIP tries to solve.If you want this functionality you are probably going to have to make a more concrete case for it than what is currently in the DIP. If there are any languages that implement it the way you want to implement it it would probably be a good idea to include them as examples.I am pretty sure this DIP listed some major languages with this feature, and it also includes concrete examples.
Feb 17 2019
On Sunday, 17 February 2019 at 17:58:56 UTC, Rubn wrote:On Sunday, 17 February 2019 at 17:09:57 UTC, Yuxuan Shui wrote:This is not valid under this DIP. Actually, this is allowed under current D too, as long as you don't call "add". With my DIP, the behavior is the same, when you call add, you will get an error because your call matches both function. Parameter name is not part of overload resolution, this is explicitly stated in the DIP.On Sunday, 17 February 2019 at 13:12:11 UTC, Rubn wrote:Yes that's very different from what you want to implement it. See below.[...]This is allowed, _right now_. This is not an addition made by this DIP. Example: https://d.godbolt.org/z/hbwsaUYes and Python doesn't behave the way you are suggesting. Listing the languages that implement the feature but not how they implement it makes the argument weaker. You list Python but I would not say Python implements this feature the same way as you are suggesting it to be implemented. I'd use Python as an example against this DIP (as I have). Eg the DIP suggests this be valid code so long as it can be distinguished by at least one parameter. named: int add(int a, int b) { ... } int add(int c, int d) { ... }[...]And they have the problem that the name of the parameter becomes part of the API. This is something this DIP tries to solve.[...]I am pretty sure this DIP listed some major languages with this feature, and it also includes concrete examples.
Feb 17 2019
After thinking about the feedback so far, I currently plan to make these changes to this DIP: * For reordering: I want to step back from reordering. It was add as an after thought, and turns out to be way more involved than I expected, and it is really not part of my goal for this DIP. * For named: Since there exist templates like ParameterIdentiferTuple, it shouldn't be hard to write a template to automatically wrap non- named functions to make them named. So this really is not a problem. If you are not satisfied with this solution (let me know), I have another proposal: named will still be part of this DIP, but if a function is not annotated with named, you can still call it with named parameters. If the names mismatch, you get a warning instead of an error. This way, API developers can clearly state their intentions with named, and don't have to take responsibilities for API breakage caused by parameter rename; OTOH, API users can still call functions with named parameters.
Feb 17 2019
On Sunday, 17 February 2019 at 21:04:23 UTC, Yuxuan Shui wrote:After thinking about the feedback so far, I currently plan to make these changes to this DIP: * For reordering: I want to step back from reordering. It was add as an after thought, and turns out to be way more involved than I expected, and it is really not part of my goal for this DIP. * For named: Since there exist templates like ParameterIdentiferTuple, it shouldn't be hard to write a template to automatically wrap non- named functions to make them named. So this really is not a problem.It is an issue if you are concern about compile time cost and generating unwanted verbiage. Templates despite powerful have a cost associated with them. -Alex
Feb 17 2019
On Sunday, 17 February 2019 at 21:04:23 UTC, Yuxuan Shui wrote:After thinking about the feedback so far, I currently plan to make these changes to this DIP: * For reordering: I want to step back from reordering. It was add as an after thought, and turns out to be way more involved than I expected, and it is really not part of my goal for this DIP. * For named: Since there exist templates like ParameterIdentiferTuple, it shouldn't be hard to write a template to automatically wrap non- named functions to make them named. So this really is not a problem. If you are not satisfied with this solution (let me know), I have another proposal: named will still be part of this DIP, but if a function is not annotated with named, you can still call it with named parameters. If the names mismatch, you get a warning instead of an error. This way, API developers can clearly state their intentions with named, and don't have to take responsibilities for API breakage caused by parameter rename; OTOH, API users can still call functions with named parameters.How about this: simply adding the ability to name the argument when calling a function? Example: void rectangle(int width, int height) {} void main() { rectangle(1, 2); rectangle(width: 1, height: 2); rectangle(height: 2, width: 1); rectangle(width: 1, 2); // error } All 3 function invocations lower to the same function call. Of course, naming should be either for all parameters or for none. This has the advantage that no code will be broken and naming will become optional. This way you have no mangling problems and you don't have to add any attributes. This solution is also easier to implement and easier to drop/enhance after we gather some information about where we need to go with this. Cheers RazvanN
Feb 18 2019
On Monday, 18 February 2019 at 08:32:02 UTC, RazvanN wrote:On Sunday, 17 February 2019 at 21:04:23 UTC, Yuxuan Shui wrote:I forgot to mention optional parameters; if there are any optional parameters and you are fine with the default value, you don't have to specify them.[...]How about this: simply adding the ability to name the argument when calling a function? Example: void rectangle(int width, int height) {} void main() { rectangle(1, 2); rectangle(width: 1, height: 2); rectangle(height: 2, width: 1); rectangle(width: 1, 2); // error } All 3 function invocations lower to the same function call. Of course, naming should be either for all parameters or for none. This has the advantage that no code will be broken and naming will become optional. This way you have no mangling problems and you don't have to add any attributes. This solution is also easier to implement and easier to drop/enhance after we gather some information about where we need to go with this. Cheers RazvanN
Feb 18 2019
On Monday, 18 February 2019 at 08:32:02 UTC, RazvanN wrote:On Sunday, 17 February 2019 at 21:04:23 UTC, Yuxuan Shui wrote:Now this is a solution that I can get behind.[...]How about this: simply adding the ability to name the argument when calling a function? Example: [...]
Feb 18 2019
On Monday, 18 February 2019 at 08:32:02 UTC, RazvanN wrote:On Sunday, 17 February 2019 at 21:04:23 UTC, Yuxuan Shui wrote:1) What about typos/wrong names? rectangle(width: 1, hight: 2) 2) How will this deal with parameter renames / deprecation? If (1) isn't checked, introducing this later would break a lot of code.[...]How about this: simply adding the ability to name the argument when calling a function? Example: void rectangle(int width, int height) {} void main() { rectangle(1, 2); rectangle(width: 1, height: 2); rectangle(height: 2, width: 1); rectangle(width: 1, 2); // error }
Feb 18 2019
On Monday, 18 February 2019 at 19:27:15 UTC, Seb wrote:On Monday, 18 February 2019 at 08:32:02 UTC, RazvanN wrote:Easy: you print the parameters that do not match: "Unknown parameter name". If a parameter name is not in the list of parameters, you print it.On Sunday, 17 February 2019 at 21:04:23 UTC, Yuxuan Shui wrote:1) What about typos/wrong names? rectangle(width: 1, hight: 2)[...]How about this: simply adding the ability to name the argument when calling a function? Example: void rectangle(int width, int height) {} void main() { rectangle(1, 2); rectangle(width: 1, height: 2); rectangle(height: 2, width: 1); rectangle(width: 1, 2); // error }2) How will this deal with parameter renames / deprecation?The easiest solution would be to simply do nothing. Once a parameter name is changed, then it has to be updated on caller site. Later on we can add smarter stuff.If (1) isn't checked, introducing this later would break a lot of code.Indeed.
Feb 18 2019
On Sunday, 17 February 2019 at 21:04:23 UTC, Yuxuan Shui wrote:After thinking about the feedback so far, I currently plan to make these changes to this DIP: ...Would you also be able to confirm how this DIP handles default arguments and templates? I think the DIP could use an example showing this off. One of my almost dally 'is there no better way?' moments with D currently is default template arguments, for example to change throwErrors currently I need to do: --- T toString(T=string, bool SomeThing=true, bool throwErrors=true, S)(S value){return "";} auto foo = 123.toString!(string, true, false); --- Where as I think something like this would be better: --- auto foo = 123.toString!(throwErrors: false); ---
Mar 21 2019
On Thursday, 21 March 2019 at 20:31:57 UTC, David Bennett wrote:On Sunday, 17 February 2019 at 21:04:23 UTC, Yuxuan Shui wrote:This DIP won't support template arguments. And with my current plan this DIP probably won't help default arguments either.After thinking about the feedback so far, I currently plan to make these changes to this DIP: ...Would you also be able to confirm how this DIP handles default arguments and templates? I think the DIP could use an example showing this off.One of my almost dally 'is there no better way?' moments with D currently is default template arguments, for example to change throwErrors currently I need to do: --- T toString(T=string, bool SomeThing=true, bool throwErrors=true, S)(S value){return "";} auto foo = 123.toString!(string, true, false); --- Where as I think something like this would be better: --- auto foo = 123.toString!(throwErrors: false); ---Yes, that would be better, but sadly that's out of the scope of this DIP.
Mar 22 2019
On Friday, 22 March 2019 at 15:18:09 UTC, Yuxuan Shui wrote:On Thursday, 21 March 2019 at 20:31:57 UTC, David Bennett wrote:That is unfortunate as its the part that gives me the most pain currently. Almost so much as to make me feel like adding a 3rd named arguments DIP that only worked on default arguments.Would you also be able to confirm how this DIP handles default arguments and templates? I think the DIP could use an example showing this off.This DIP won't support template arguments. And with my current plan this DIP probably won't help default arguments either.
Apr 01 2019
On Sunday, 17 February 2019 at 20:58:04 UTC, Yuxuan Shui wrote:On Sunday, 17 February 2019 at 17:58:56 UTC, Rubn wrote:How does it decide which function to call in this case, straight from the DIP, go through the entire process cause the DIP is rather ambiguous. Specifically if parameter names are not included in the mangled name of a function per the feature not being part of the scope of the DIP.On Sunday, 17 February 2019 at 17:09:57 UTC, Yuxuan Shui wrote:This is not valid under this DIP. Actually, this is allowed under current D too, as long as you don't call "add". With my DIP, the behavior is the same, when you call add, you will get an error because your call matches both function. Parameter name is not part of overload resolution, this is explicitly stated in the DIP.On Sunday, 17 February 2019 at 13:12:11 UTC, Rubn wrote:Yes that's very different from what you want to implement it. See below.[...]This is allowed, _right now_. This is not an addition made by this DIP. Example: https://d.godbolt.org/z/hbwsaUYes and Python doesn't behave the way you are suggesting. Listing the languages that implement the feature but not how they implement it makes the argument weaker. You list Python but I would not say Python implements this feature the same way as you are suggesting it to be implemented. I'd use Python as an example against this DIP (as I have). Eg the DIP suggests this be valid code so long as it can be distinguished by at least one parameter. named: int add(int a, int b) { ... } int add(int c, int d) { ... }[...]And they have the problem that the name of the parameter becomes part of the API. This is something this DIP tries to solve.[...]I am pretty sure this DIP listed some major languages with this feature, and it also includes concrete examples.int add(int a, int b) {...} int add(int c, int d) {...} // not in the overload set void main() { add(a: 1, b: 2); } It might be useful to have parameter names included in the mangled name of a function so that changing the ordering of parameters does not break existing binaries. Such is beyond the scope of this DIP. A future DIP may address this issue.
Feb 17 2019
On Sunday, 17 February 2019 at 17:09:57 UTC, Yuxuan Shui wrote:On Sunday, 17 February 2019 at 13:12:11 UTC, Rubn wrote:That seems to be a misunderstanding of what that example does. The first two declarations are just declaring that a function should exist with the signature `int fun(int, int)`. The third declaration actually implements that function. If OTOH you delete the implementation and use `dmd -c` to compile without linking, you'll get the expected overload-related error, whether or not you have the same or different parameter names, or no parameter names at all, in those first two declarations.Allowing two functions to exist with the same type signature just adds unnecessary complexity.This is allowed, _right now_. This is not an addition made by this DIP. Example: https://d.godbolt.org/z/hbwsaU
Feb 27 2019
On Saturday, 16 February 2019 at 23:56:45 UTC, Vladimir Panteleev wrote:named is not the best idea.I discourage named, too. The lesser evil is when implementors break call sites whenever implementors rename their arguments. It's rare that this happens purely for style. (If the renaming is caused by a semantic change in the function, then we want noisy breakage in the call sites anyway, with or without named.) Function designers are already annotating everything with property const safe pure nothrow nogc. Let's not bloat the definition even more with named. Besides named, I'm happy with the proposal. Expressiveness and automatic checks are good. -- Simon
Feb 18 2019
I might be misunderstanding something, but with this code: int add(int x, int y); named: int add(int c, int d); What happens if I do add(5, 6)? Won't that be ambiguous?
Feb 17 2019
On Sunday, 17 February 2019 at 18:23:13 UTC, Elronnd wrote:I might be misunderstanding something, but with this code: int add(int x, int y); named: int add(int c, int d); What happens if I do add(5, 6)? Won't that be ambiguous?All declarations with the same signature must refer to the same function. Or, in other words, only one of them can have a function body, and that body will be used for all calls that match any of the equivalent declarations. Redundant declarations like this are actually already allowed in D; there just isn't any particular reason you'd want to use them. Example: https://run.dlang.io/is/MSmiF5
Feb 17 2019
On Friday, February 15, 2019 5:56:45 AM MST Mike Parker via Digitalmars-d wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa 6/DIPs/DIP1019.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment by the language maintainers. Please familiarize yourself with the documentation for the Community Review before participating. https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review Thanks in advance to all who participate.I honestly don't understand the whole deal about discussing "repurposing" function parameters. If you refactor a function, it needs to continue to work with all existing calls to it, or it's going to break code. So, stuff like swapping x and y and the like make absolutely no sense. If you're going to screw up existing function calls by changing the function's signature, then you can't change the function's signature. So, I don't see any point in even worrying about function parameters being repurposed. Personally, I hope that we never have any form of named arguments in D (beyond whatever folks do with libraries, though I hope never have to deal with code that uses such libraries). But ultimately, that's going to be up to Walter and Andrei... I do approve of the fact that this DIP doesn't automatically enable named arguments everywhere, since I really, really, really don't want to have parameters be part of the API if I can possibly avoid it, and I would never use named anywhere if this DIP gets approved - though in all likelihood, that will result in arguments about whether folks should slap named on functions or not between folks who want named arguments and those who don't. So, approval of the DIP with such an attribute could become pretty divisive with regards to how folks write libraries. I'm not sure that you can punt the name mangling issue like the DIP currently does. It's currently legal to declare functions without even having parameter names (let alone requiring that the parameter names match) when you deal with stuff like .di files. It also affects what happens with functions that aren't extern(D). For instance, it's perfectly legal to put pure or nothrow on an extern(C) function declaration, and that affecs how the D code uses it, but it has no effect on the name mangling. If named arguments affect the name mangling, then they will only work with extern(D) functions, but if they don't, then you have issues when a function's declaration doesn't match its definition with regards to its parameters' names. - Jonathan M Davis
Feb 26 2019
On Wednesday, 27 February 2019 at 02:17:30 UTC, Jonathan M Davis wrote:Personally, I hope that we never have any form of named arguments in D (beyond whatever folks do with libraries, though I hope never have to deal with code that uses such libraries). But ultimately, that's going to be up to Walter and Andrei...Curious. How come? Would it not be nicer for contributors to know what "TexPos(1, 1)" (from your dxml library) does without having to lookup TextPos? I actually got it wrong from just reading the source. I thought it was pixel positions x, y. But nope. Another thing is that almost every time I see std.traits anywhere, I NEVER know which argument is what and always have to look it up. Multiply this by every programmer who has to code review, or maintain code and it's a lot of wasted time that's solved with proper use of named arguments. Some arguments I have heard about against named arguments though: 1) verbosity of call-site - solvable when named arguments are optional, should the API designer think so. It's the same as if an API designer decides to call a publicly accessible property "config" or "configuration". If there's a function that takes one argument, it makes little sense for an API writer to force it to be named. But as long as that choice is given, the purpose is to make the function as natural as possible. 2) Parameter lock in - don't see how that's different than function name lock in. Choose a name, use it. It goes through code reviews. If you change it, you bump a version number. I guess the number of places where the api can break increases though. But from a number of years of experience, I have not experienced this. Plus, I tend to find that API "superficially" used named arguments Example from std: topN(r, 3) topNCopy(r1, r2) topNIndex(r1, i1) These are the same function with different named arguments: topN(r, 3) topN(r, copy: r2) topN(r, index: r2) But since you don't have named arguments you put the name part of the arguments in the function name. 3) Needing to think about parameter names. You don't if they're optional. As the API designer. You need to think about the public interface of your function name anyway. And, if you're making public APIs, you're making docs (I hope). So you're already doing this. You would have to think if the API required named arguments or not though. 4) ?? Cheers, - Ali
Feb 27 2019
On Wednesday, 27 February 2019 at 02:17:30 UTC, Jonathan M Davis wrote:On Friday, February 15, 2019 5:56:45 AM MST Mike Parker via Digitalmars-d wrote:I don't agree with this at all. The feature becomes all but useless, it's either all in or just don't include it. So many things are already part of the API, and this will be an opt-in feature for the user (not the library developer). The user can choose to use the variable names if they want, knowing full well if the author pleases they can change it, but this will be no different than changing the variable name of struct.This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa 6/DIPs/DIP1019.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on March 1, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment by the language maintainers. Please familiarize yourself with the documentation for the Community Review before participating. https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review Thanks in advance to all who participate.I do approve of the fact that this DIP doesn't automatically enable named arguments everywhere, since I really, really, really don't want to have parameters be part of the API if I can possibly avoid it, and I would never use named anywhere if this DIP gets approved - though in all likelihood, that will result in arguments about whether folks should slap named on functions or not between folks who want named arguments and those who don't. So, approval of the DIP with such an attribute could become pretty divisive with regards to how folks write libraries.
Feb 28 2019
On Friday, 1 March 2019 at 00:49:25 UTC, Rubn wrote:I don't agree with this at all. The feature becomes all but useless, it's either all in or just don't include it. So many things are already part of the API, and this will be an opt-in feature for the user (not the library developer). The user can choose to use the variable names if they want, knowing full well if the author pleases they can change it, but this will be no different than changing the variable name of struct.It's not comparable to changing the variable name of a struct, because if that struct is a public data structure in a library, changing its field names is a breaking change. Downstream users should be able to rely on a library maintainer not doing that except in a major release (and even then, providing a clear heads-up and transition path; it might work in some cases to e.g. rename the struct field but add a `deprecated alias oldName = newName`, and then drop that alias only in the next major release). If the language design is changed so that downstream users _can_ use named arguments, then library maintainers have to assume that they _will_, and treat parameter names accordingly. It's no good just saying "I don't support this", because if you can't enforce such a constraint ahead of time, you are on a hiding to nothing. If API opt-in to named parameter support is not adequate, then it's better to drop the feature request entirely, because it is not reasonable to impose a big new responsibility like named arguments on maintainers of existing codebases.
Mar 03 2019
On Sunday, 3 March 2019 at 10:50:05 UTC, Joseph Rushton Wakeling wrote:If API opt-in to named parameter support is not adequate, then it's better to drop the feature request entirely, because it is not reasonable to impose a big new responsibility like named arguments on maintainers of existing codebases.I think you're overstating how big the responsibility is. Maintainers can still change argument names with the current DIP, they just need to keep exporting a prototype with the old names.
Mar 03 2019
On Sunday, 3 March 2019 at 12:46:22 UTC, Olivier FAURE wrote:Maintainers can still change argument names with the current DIP, they just need to keep exporting a prototype with the old names.Well, since the current DIP is entirely opt-in from the function author side anyway, it's a bit of a moot point. I was responding rather to someone who was arguing that it should _not_ be opt in for function authors.
Mar 03 2019
On Sunday, 3 March 2019 at 15:07:04 UTC, Joseph Rushton Wakeling wrote:Well, since the current DIP is entirely opt-in from the function author side anyway, it's a bit of a moot point. I was responding rather to someone who was arguing that it should _not_ be opt in for function authors.My point was, the DIP should be opt-out, because even then library maintainers can always change argument names if they want to, without breaking code. And even if code does break, it's an extremely easy fix (as in, "change a few names until it compiles", not "refactor everything"). Like, okay, I get that some people are opposed to the very idea of parameter names being important information to keep track of, but pragmatically, the costs of making named arguments the default are far outweighed by the benefits.
Mar 04 2019
On Mon, Mar 04, 2019 at 06:57:16PM +0000, Olivier FAURE via Digitalmars-d wrote:On Sunday, 3 March 2019 at 15:07:04 UTC, Joseph Rushton Wakeling wrote:IMNSHO, even if parameter names aren't important information to keep track of, being forced to accomodate renamings would motivate people to actually invent useful, self-explanatory parameter names rather than `func(int a, int b, int c)` or worse, `func(int, int, int)`, with no indication as to what the parameter is supposed to mean. T -- WINDOWS = Will Install Needless Data On Whole System -- CompuManWell, since the current DIP is entirely opt-in from the function author side anyway, it's a bit of a moot point. I was responding rather to someone who was arguing that it should _not_ be opt in for function authors.My point was, the DIP should be opt-out, because even then library maintainers can always change argument names if they want to, without breaking code. And even if code does break, it's an extremely easy fix (as in, "change a few names until it compiles", not "refactor everything"). Like, okay, I get that some people are opposed to the very idea of parameter names being important information to keep track of, but pragmatically, the costs of making named arguments the default are far outweighed by the benefits.
Mar 04 2019
On Monday, 4 March 2019 at 18:57:16 UTC, Olivier FAURE wrote:On Sunday, 3 March 2019 at 15:07:04 UTC, Joseph Rushton Wakeling wrote:I agree that, having named arguments as the default would be better, _if_ we are designing a new language from ground up. With D, even if we want to eventually make named arguments the default, it have to go through a deprecation path. IMHO, this is what a mature language should do.Well, since the current DIP is entirely opt-in from the function author side anyway, it's a bit of a moot point. I was responding rather to someone who was arguing that it should _not_ be opt in for function authors.My point was, the DIP should be opt-out, because even then library maintainers can always change argument names if they want to, without breaking code. And even if code does break, it's an extremely easy fix (as in, "change a few names until it compiles", not "refactor everything"). Like, okay, I get that some people are opposed to the very idea of parameter names being important information to keep track of, but pragmatically, the costs of making named arguments the default are far outweighed by the benefits.
Mar 22 2019
On Friday, 22 March 2019 at 15:23:54 UTC, Yuxuan Shui wrote:I agree that, having named arguments as the default would be better, _if_ we are designing a new language from ground up. With D, even if we want to eventually make named arguments the default, it have to go through a deprecation path. IMHO, this is what a mature language should do.Deprecation is typically used for changes to existing functionality that could break existing code. For example, the upcoming change to enable DIP 25 by default requires a deprecation process, because enabling DIP 25 will cause some code that currently works to fail to compile. Named arguments, however, are a purely additive change to the language. They will not break any existing D code, because all existing D code uses positional arguments, and positional arguments will continue to work the same way they always have. Why, then, is a deprecation process necessary?
Mar 22 2019
On Sunday, 3 March 2019 at 10:50:05 UTC, Joseph Rushton Wakeling wrote:On Friday, 1 March 2019 at 00:49:25 UTC, Rubn wrote:Agree completely. Finally someone arguing from this side :)I don't agree with this at all. The feature becomes all but useless, it's either all in or just don't include it. So many things are already part of the API, and this will be an opt-in feature for the user (not the library developer). The user can choose to use the variable names if they want, knowing full well if the author pleases they can change it, but this will be no different than changing the variable name of struct.It's not comparable to changing the variable name of a struct, because if that struct is a public data structure in a library, changing its field names is a breaking change. Downstream users should be able to rely on a library maintainer not doing that except in a major release (and even then, providing a clear heads-up and transition path; it might work in some cases to e.g. rename the struct field but add a `deprecated alias oldName = newName`, and then drop that alias only in the next major release). If the language design is changed so that downstream users _can_ use named arguments, then library maintainers have to assume that they _will_, and treat parameter names accordingly. It's no good just saying "I don't support this", because if you can't enforce such a constraint ahead of time, you are on a hiding to nothing. If API opt-in to named parameter support is not adequate, then it's better to drop the feature request entirely, because it is not reasonable to impose a big new responsibility like named arguments on maintainers of existing codebases.
Mar 04 2019
I would broadly second Jonathan's remarks above: https://forum.dlang.org/post/mailman.7211.1551233866.29801.digitalmars-d puremagic.com ... but a few thoughts in my own words. First, I think my core objection to this proposal is that ultimately, it's a cosmetic change to language syntax that does not make any meaningful improvement to the kinds of programs one can write, or to the compiler's ability to prove their safety and correctness -- even allowing that it's opt-in, implementing support is going to be finnicky and intrusive, and risks nasty impacts on stuff that affects _all_ programs (e.g. name mangling). If we consider the languages where named arguments are a feature, virtually all of them are scripting (or scriptable) languages where it's common to use them via a REPL, and the use-case is for functions that have a lot of parameters, where in the typical use-case the caller only wants to specify the ones that are non-default. In a scripting language, it's convenient to allow the user to just make the one function call. But in a systems programming language it's both straightforward and arguably better self-documenting to do something like: ``` struct Config { // default values for everything int alpha = 23; double beta = 0.25; int gamma = 6; double delta = 1.5; // ... int omega = 99; } double foo (Config config) { with(config) { // implementation } } ``` and then one can call with e.g.: ``` Config config = { beta: 6.5, omega: 101 }; auto result = foo(config); ``` As others have already pointed out, it needs only some small improvements to the struct declaration mechanisms to allow us to do something like: ``` foo({ beta: 6.5, omega: 101 }); ``` ... without even needing to declare a separate Config instance. This sort of approach will work naturally with UFCS: ``` double bar (int a, Config config) { ... } x.bar({ delta: 9.125, gamma: 7}); ``` ... so one therefore has the effect of named parameters without any real change to the language syntax or behaviour. On the question of "protecting against silent breakage in cases when a function's parameters are repurposed and renamed": this seems a very narrow protection compared to all the ways in which one can introduce breaking change into a function. And by contrast it blocks something that can be very useful, which is renaming a function parameter to better illustrate its meaning, _without_ changing its purpose. Specific feedback on a few points: * `Completeness`: note that this approach of "all named or none" is in contrast with various languages' approach to named parameters, where it's common to have some initial obligatory parameters plus the option to set extra config variables. Think Python, e.g. in this usage from the `pandas` data science library: dates = pd.date_range('20190227', periods=6) This should be noted as a contrast with what is being proposed in the current DIP. (The struct-based approach outlined above may allow something closer to this, albeit imperfectly.) * in the `Overloading and name mangling` section it would be good to have contrasting examples of what happens when parameter names are identical but types are different, e.g.: int add(int a, int b) {...} double add(double a, double b) {...} ... and a clear description of how template functions and methods will be impacted, e.g. `T add(T)(T a, T b)`. * `Alternatives` should be updated to note the struct-based approach described above and by others, which does not need any specific support beyond perhaps improvements proposed in the DIP currently being drafted at https://github.com/wilzbach/DIPs/blob/b1283b455b635d7dcbc2c871d2aa47cc67190059/DIPs/DIP1xxx-sw.md In summary: * despite being opt-in only, the proposal still seems an intrusive change for limited practical benefit * suggestions by others that named parameters should be opt-out would make it even more intrusive, and impose a massive unasked-for maintenance burden on existing library maintainers * some small improvements to struct initialization would make it possible to get a syntax and behaviour very close to that wanted, while keeping entirely within existing idiomatic language syntax and style Hope that helps!
Feb 27 2019
On Wednesday, 27 February 2019 at 12:49:52 UTC, Joseph Rushton Wakeling wrote:If we consider the languages where named arguments are a feature, virtually all of them are scripting (or scriptable) languages where it's common to use them via a REPL, and the use-case is for functions that have a lot of parameters, where in the typical use-case the caller only wants to specify the ones that are non-default.Swift, Dart, Objective-C are definitely not scripting languages and they aren't primarily used through repr, and they all support named/keyword arguments in some form.As others have already pointed out, it needs only some small improvements to the struct declaration mechanisms to allow us to do something like: ``` foo({ beta: 6.5, omega: 101 }); ```This would be great.
Feb 27 2019
On Wednesday, 27 February 2019 at 18:16:32 UTC, JN wrote:On Wednesday, 27 February 2019 at 12:49:52 UTC, Joseph Rushton Wakeling wrote:It would be great indeed, but insufficient. At least I can't find a reasonble struct based solution which handle default arguments correctly. struct dim { uint w=5; uint h=5; } void foo(dim d={w:10, h:10}){} void bar(dim d={w:20, h:20}){} foo({w:50}); // h should default to 10 but it likely will be 5 bar({w:50}); // h should default to 20 but it likely will be 5``` foo({ beta: 6.5, omega: 101 }); ```This would be great.
Feb 27 2019
On Wednesday, 27 February 2019 at 18:51:40 UTC, Daniel N wrote:It would be great indeed, but insufficient. At least I can't find a reasonble struct based solution which handle default arguments correctly. struct dim { uint w=5; uint h=5; } void foo(dim d={w:10, h:10}){} void bar(dim d={w:20, h:20}){} foo({w:50}); // h should default to 10 but it likely will be 5 bar({w:50}); // h should default to 20 but it likely will be 5I wonder if you have a real-world example of this requirement (same named parameters but different requirements for defaults)? I ask because it seems like the best way to address the concern is likely to be contingent on the particular use case. The example given considers the input as a type encoding the set of parameter names and types, with default values as something extraneous. It feels like that's the conceptual problem: the input type should encode parameter names, types, and defaults all together. In other words, `foo` and `bar` should have different struct types (with different default values to their fields) as input. Clunky and maybe a bit boilerplate-y? Yes, but much less intrusive than introducing a syntax change that has significant impact on the maintainability of much already existing code. Note that this would be simpler from a developer point of view if it was possible to declare "anonymous" structs in place in the function declarations, i.e.: int foo (struct { int w = 10; int h = 10; }); int bar (struct { int w = 20; int h = 20; }); ... which combined with the earlier suggestion would also be a fairly natural extension of existing struct syntax.
Mar 03 2019
On Sunday, 3 March 2019 at 09:36:32 UTC, Joseph Rushton Wakeling wrote:Note that this would be simpler from a developer point of view if it was possible to declare "anonymous" structs in place in the function declarations, i.e.: int foo (struct { int w = 10; int h = 10; }); int bar (struct { int w = 20; int h = 20; }); ... which combined with the earlier suggestion would also be a fairly natural extension of existing struct syntax.I think this approach gives every parameter a default value, and thus make them all optional. Which is not necessarily desirable.
Mar 04 2019
On Monday, 4 March 2019 at 12:00:54 UTC, Yuxuan Shui wrote:I think this approach gives every parameter a default value, and thus make them all optional. Which is not necessarily desirable.Agreed. It was an example of how to solve (essentially within current D idioms) a particular subset of the problems where named arguments are useful.
Mar 04 2019
On Wednesday, 27 February 2019 at 12:49:52 UTC, Joseph Rushton Wakeling wrote:... First, I think my core objection to this proposal is that ultimately, it's a cosmetic change to language syntax that does not make any meaningful improvement to the kinds of programs one can write, or to the compiler's ability to prove their safety and correctnessYes it does!! That is in fact the main argument for it! It allows the compiler to do a *much* better job at ensuring the correctness of programs, by attaching parameters to semantic labels instead of passing them by arbitrary positions and hoping that the type system will happen to catch errors.even allowing that it's opt-in, implementing support is going to be finnicky and intrusive, and risks nasty impacts on stuff that affects _all_ programs (e.g. name mangling).Only if you do it in a weird way. There's no *necessary* reason for named parameters to affect mangling at all.If we consider the languages where named arguments are a feature, virtually all of them are scripting (or scriptable) languages where it's common to use them via a REPL, and the use-case is for functions that have a lot of parameters, where in the typical use-case the caller only wants to specify the ones that are non-default. In a scripting language, it's convenient to allow the user to just make the one function call. But in a systems programming language it's both straightforward and arguably better self-documenting to do something like: ``` struct Config { // default values for everything int alpha = 23; double beta = 0.25; int gamma = 6; double delta = 1.5; // ... int omega = 99; } double foo (Config config) { with(config) { // implementation } } ``` and then one can call with e.g.: ``` Config config = { beta: 6.5, omega: 101 }; auto result = foo(config); ```And even that is one case where named parameters represent a *huge* improvement! If a new parameter is added to Config, there is *absolutely* no way to require it to be passed. You have to use something like my own `boilerplate.Builder()`, and even that just gives you an exception at compiletime. struct Foo { int a; int b; mixin(GenerateThis); } with (Foo.Builder()) { a = 2; return value; // runtime error: necessary field b not assigned // but no compile error because :( :( :( } There is *no way* to statically enforce that a field was set in a struct. Parameters on the other hand do this effortlessly. I'd *love* to ditch Boilerplate's generated builders and replace them with named parameters. The lack of named parameters is why that hacky expensive feature even exists to begin with.As others have already pointed out, it needs only some small improvements to the struct declaration mechanisms to allow us to do something like: ``` foo({ beta: 6.5, omega: 101 }); ``` ... without even needing to declare a separate Config instance. This sort of approach will work naturally with UFCS: ``` double bar (int a, Config config) { ... } x.bar({ delta: 9.125, gamma: 7}); ``` ... so one therefore has the effect of named parameters without any real change to the language syntax or behaviour.Yeah at the cost of breaking struct behavior, or you still don't have any way to have necessary parameters.On the question of "protecting against silent breakage in cases when a function's parameters are repurposed and renamed": this seems a very narrow protection compared to all the ways in which one can introduce breaking change into a function. And by contrast it blocks something that can be very useful, which is renaming a function parameter to better illustrate its meaning, _without_ changing its purpose.I have literally never done that, whereas I reorder function parameters relatively often. Do you really rename function parameters more often than inserting a new required parameter in the middle?
Feb 28 2019
On Thursday, 28 February 2019 at 08:32:22 UTC, FeepingCreature wrote:I have literally never done that, whereas I reorder function parameters relatively often. Do you really rename function parameters more often than inserting a new required parameter in the middle?A function taking more than 2 parameters is a design flaw on its own, I think. Let alone adding new parameters _in_the_middle_ (shudder). You should almost always be better off taking a struct as parameter.
Feb 28 2019
On Thursday, 28 February 2019 at 09:22:31 UTC, Dominikus Dittes Scherkl wrote:A function taking more than 2 parameters is a design flaw on its own, I think. Let alone adding new parameters _in_the_middle_ (shudder). You should almost always be better off taking a struct as parameter.Considering D is billed as a multiparadigm language, I'd be surprised to hear that the intended usecase does not include "functions with more than two parameters". This comment seems quite far from practiced reality. In any case, passing a struct is a horrible solution, because, again, there is no way for structs to even enforce that *all* fields were set, let alone some subset, short of spamming Nullable.
Feb 28 2019
On Thursday, 28 February 2019 at 08:32:22 UTC, FeepingCreature wrote:Yes it does!! That is in fact the main argument for it! It allows the compiler to do a *much* better job at ensuring the correctness of programs, by attaching parameters to semantic labels instead of passing them by arbitrary positions and hoping that the type system will happen to catch errors.This could sometimes be nice, but the question is whether the extra benefits are worth it compared to the problems caused by imposing a major semantic change on the language.If a new parameter is added to Config, there is *absolutely* no way to require it to be passed. You have to use something like my own `boilerplate.Builder()`, and even that just gives you an exception at compiletime. [... snip ...] There is *no way* to statically enforce that a field was set in a struct.That's certainly a reasonable objection. The question is not, does this cover _all_ use cases for named parameters, but does it cover some of the major ones that matter? (For example, the case of multiple different parameters where one only wants to set the ones that need to be non-default.)Parameters on the other hand do this effortlessly. I'd *love* to ditch Boilerplate's generated builders and replace them with named parameters. The lack of named parameters is why that hacky expensive feature even exists to begin with.I'm not familiar with your Boilerplate library, so difficult to comment -- are you saying here that the library's features could be implemented more straightforwardly (or with a nicer API for users) if named parameters were a thing? Or that features of the library would not need to exist in the first place? I ask because it's possible that the requirements here are arriving more out of preferences for how to write the downstream code, than about problems with writing idiomatically in D as it is right now.I have literally never done that, whereas I reorder function parameters relatively often. Do you really rename function parameters more often than inserting a new required parameter in the middle?In what context do you reorder or insert new function parameters often? In public functions or methods of a library? In internals private to a library or app? And what's the motivation for such re-ordering? I ask because I wonder if there aren't other entirely adequate methods for managing those transitions that don't rely on named parameters, and which are more idiomatic to D as it already exists. If you have concrete examples we could probably discuss those. I accept that named parameters might make some of these transitions easier, but that has to be weighed against the disruption of introducing that feature to a language where a large amount of code has already been written without that feature in mind.
Mar 03 2019
On Friday, 15 February 2019 at 12:56:45 UTC, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite":The proposal mentioned that having two named functions with same names and parameter types but different parameter names is allowed. However, this does imply named functions have different mangling than a similar unnamed function. I think the DIP should mention whether this means that extern(!D) functions are forbidden altogether, or just don't consider parameter names in overload resolution. The above brings this proposal closer to what Rikki did propose. IMO this proposal has better syntax, but Rikki's proposal has the advantage that named parameters can be combined with unnamed parameters. In any case, I think they should go to formal assesment together. Either one will be a step forward.
Feb 27 2019
On Wednesday, 27 February 2019 at 17:46:24 UTC, Dukc wrote:The proposal mentioned that having two named functions with same names and parameter types but different parameter names is allowed.No, it mentions that having two named prototypes for the same functions with the same name and parameter types but different parameters is allowed. eg: This is forbidden: named: int foo(int x, int y) { return x + y; } int foo(int w, int z) { return w + z; } and this is allowed: named: int foo(int x, int y); int foo(int w, int z) { return y + z; } The next iteration should probably make that distinction clearer.
Feb 28 2019
On Thursday, 28 February 2019 at 21:55:50 UTC, Olivier FAURE wrote:No, it mentions that having two named prototypes for the same functions with the same name and parameter types but different parameters is allowed. eg: This is forbidden: named: int foo(int x, int y) { return x + y; } int foo(int w, int z) { return w + z; } and this is allowed: named: int foo(int x, int y); int foo(int w, int z) { return y + z; } The next iteration should probably make that distinction clearer.Is the idea here that you can effectively define "aliases" for the parameter names (e.g. to help transitions), but not have multiple function implementations with the same type signatures and different names? That presumably impacts back on the mangling question, and whether the parameter names need to be included in the function mangling ... ?
Mar 01 2019
On Friday, 1 March 2019 at 13:37:24 UTC, Joseph Rushton Wakeling wrote:On Thursday, 28 February 2019 at 21:55:50 UTC, Olivier FAURE wrote:Function names won't be included in mangling. It is a bit complicated now since this version of this DIP includes reordering, but the next revision won't.[...]Is the idea here that you can effectively define "aliases" for the parameter names (e.g. to help transitions), but not have multiple function implementations with the same type signatures and different names? That presumably impacts back on the mangling question, and whether the parameter names need to be included in the function mangling ... ?
Mar 04 2019
On 2/15/19 7:56 AM, Mike Parker wrote:This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f4 aa6/DIPs/DIP1019.mdThings 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 06 2019
On Thu, Jun 06, 2019 at 12:31:14PM -0400, Andrei Alexandrescu via Digitalmars-d wrote:On 2/15/19 7:56 AM, Mike Parker wrote:[...]This is the feedback thread for the first round of Community Review for DIP 1019, "Named Arguments Lite": https://github.com/dlang/DIPs/blob/23ef47a94e0fdd5ddc4b2f6b2f4dcfd3c1f43aa6/DIPs/DIP1019.md* "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).[...] Yeah, these 2 points are also what greatly weakens this DIP, IMO, because they could be construed to be the raison d'etre of named arguments in the first place. Not having them makes one wonder what's the point of this DIP in the first place. As Amaury said in his DConf lightning talk, we don't want 95% features (or in this case, more like 50% features -- halfway there but missing major benefits of having named arguments in the first place). We want 100% features that provide core benefits, without being crippled in some way that makes them useless in non-trivial cases. T -- 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
Jun 06 2019