June 07, 2019
On Friday, 7 June 2019 at 11:30:02 UTC, Adam D. Ruppe wrote:
> On Friday, 7 June 2019 at 05:37:25 UTC, Jonathan Marler wrote:
>> I think there are pros and cons to exposing all parameters names to all callers.
>
> We already have this though.
>

I think exposed via reflection vs exposed via direct access makes a difference. Even if private fields are exposed via reflection, there's still an understanding that the type is still "compatible" with other versions of itself that reorganize those private fields.

June 07, 2019
On Friday, 7 June 2019 at 12:09:51 UTC, Yuxuan Shui wrote:
> On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
>> On Wednesday, 5 June 2019 at 13:03:26 UTC, Mike Parker wrote:
>>> This is the feedback thread for the second round of Community Review for DIP 1019, "Named Arguments Lite":
>>>
>>> https://github.com/dlang/DIPs/blob/9c9cc39246de4c449fe1e6cb6b27f7e426ff1eb9/DIPs/DIP1019.md
>>>
>>> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on June 19, or when I make a post declaring it complete.
>>>
>>> At the end of Round 2, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment.
>>>
>>> I have recently made minor revisions to the DIP process and implemented guidelines for reviewers. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines:
>>>
>>> https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md
>>>
>>> I also recommend that everyone read my recent blog post on the topic:
>>>
>>> https://dlang.org/blog/2019/06/04/revisions-to-the-dip-process/
>>>
>>> To be clear, I will be moving (copying, deleting, and pasting in a new thread) posts that do not adhere to the reviewer guidelines. Please direct any comments on the new documentation to a new thread or to personal email. Please, let's keep the review discussion on topic.
>>>
>>> Thanks in advance to all who participate.
>>
>> There's a big issue with this DIP.  It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it.  I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e.
>>
>> add(int x, int y) // parameter names not helpful
>> square(float x)  // parameter names not helpful
>> write(string s) // parameter names not helpful
>> void opEquals(T)(ref T other) // parameter names not helpful
>>
>> Of course there are many cases where named arguments are very helpful (the DIP provides some examples of this).
>>
>> However, if you suddenly allow every caller to specify the argument names to any parameter on any function, you've added a whole new set of dependencies between every function and its callers.  A layer of protection/encapsulation has been completely removed.  It would be like if we suddenly disabled the "private" modifier and allowed everything to access private fields within structs and classes.
>>
>> Languages like python that uses kwargs don't expose the names of all parameters.  They are able to pick and choose which parameters should be named.  This allows them to keep that layer of protection/encapsulation for the parameters where the name doesn't matter to the caller, just like when you have private fields where the name doesn't matter to an outside component.  D should follow this pattern as it has been successful in other languages and the alternative has too much disadvantage.  Allowing a parameter to be named at the call-site should be an "opt-in" feature done at the function definition, so as not to expose the names of all the other parameters that don't make sense to expose to the caller.
>
> Where were you during the last community review? :)
>
> Last time literally _everyone_ is arguing against named parameters being opt-in, and that's why I removed the opt-in-ness (the @named attribute) from the DIP.
>

I'm not actually sure if they should be opt-in. I'm pointing out the problem with them always being on. They way I suggested for them to be opt-in has 2 problems. One is that libraries will need to break compatibility with older compilers to enable them. Without opt-in, only the caller needs to do this. The second is that it users will have to wait for libraries to update before they can use the feature, and libraries may be hesitant to update to remain compatible with older compilers, at least for a while.

I'm just pointing out a problem I see. We should all be aware of the problem. Whether or not the problem is a big deal or had a good solution is another question. I think it's a big deal, and we should solve it if we can.

>> It would be like if we suddenly disabled the "private" modifier and allowed everything to access private fields within structs and classes.
>
> I don't think this is a fair comparison.

Its not a perfect comparison. Getting rid of private on all fields would be much worse than only exposing parameter names. I would say it's a more mild version of removing private semantics.
June 07, 2019
On Friday, 7 June 2019 at 15:15:40 UTC, Jonathan Marler wrote:
> On Friday, 7 June 2019 at 12:09:51 UTC, Yuxuan Shui wrote:
>> On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
>>> On Wednesday, 5 June 2019 at 13:03:26 UTC, Mike Parker wrote:
>>>> This is the feedback thread for the second round of Community Review for DIP 1019, "Named Arguments Lite":
>>>>
>>>> https://github.com/dlang/DIPs/blob/9c9cc39246de4c449fe1e6cb6b27f7e426ff1eb9/DIPs/DIP1019.md
>>>>
>>>> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on June 19, or when I make a post declaring it complete.
>>>>
>>>> At the end of Round 2, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment.
>>>>
>>>> I have recently made minor revisions to the DIP process and implemented guidelines for reviewers. Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines:
>>>>
>>>> https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md
>>>>
>>>> I also recommend that everyone read my recent blog post on the topic:
>>>>
>>>> https://dlang.org/blog/2019/06/04/revisions-to-the-dip-process/
>>>>
>>>> To be clear, I will be moving (copying, deleting, and pasting in a new thread) posts that do not adhere to the reviewer guidelines. Please direct any comments on the new documentation to a new thread or to personal email. Please, let's keep the review discussion on topic.
>>>>
>>>> Thanks in advance to all who participate.
>>>
>>> There's a big issue with this DIP.  It immediately allows any function call to increase coupling with the corresponding function definition with no way to disable it.  I agree that named parameters can increase readability, however, in the majority of cases they actually just add extra noise, i.e.
>>>
>>> add(int x, int y) // parameter names not helpful
>>> square(float x)  // parameter names not helpful
>>> write(string s) // parameter names not helpful
>>> void opEquals(T)(ref T other) // parameter names not helpful
>>>
>>> Of course there are many cases where named arguments are very helpful (the DIP provides some examples of this).
>>>
>>> However, if you suddenly allow every caller to specify the argument names to any parameter on any function, you've added a whole new set of dependencies between every function and its callers.  A layer of protection/encapsulation has been completely removed.  It would be like if we suddenly disabled the "private" modifier and allowed everything to access private fields within structs and classes.
>>>
>>> Languages like python that uses kwargs don't expose the names of all parameters.  They are able to pick and choose which parameters should be named.  This allows them to keep that layer of protection/encapsulation for the parameters where the name doesn't matter to the caller, just like when you have private fields where the name doesn't matter to an outside component.  D should follow this pattern as it has been successful in other languages and the alternative has too much disadvantage.  Allowing a parameter to be named at the call-site should be an "opt-in" feature done at the function definition, so as not to expose the names of all the other parameters that don't make sense to expose to the caller.
>>
>> Where were you during the last community review? :)
>>
>> Last time literally _everyone_ is arguing against named parameters being opt-in, and that's why I removed the opt-in-ness (the @named attribute) from the DIP.
>>
>
> I'm not actually sure if they should be opt-in. I'm pointing out the problem with them always being on. They way I suggested for them to be opt-in has 2 problems. One is that libraries will need to break compatibility with older compilers to enable them. Without opt-in, only the caller needs to do this. The second is that it users will have to wait for libraries to update before they can use the feature, and libraries may be hesitant to update to remain compatible with older compilers, at least for a while.
>
> I'm just pointing out a problem I see. We should all be aware of the problem. Whether or not the problem is a big deal or had a good solution is another question. I think it's a big deal, and we should solve it if we can.
>

C# has had named arguments for quite a while now without any way to opt in or opt out. If you want to name a function argument, you just do it. If it breaks, it breaks. I haven't seen breakage from that in practice, yet. Mostly, because people only use that syntax for complex functions that have long parameter lists or challenging parameter lists with 4 to 5 boolean parameters in row or something borderline insane like that. So, I'd say that it's in the ballpark of one in 1000 LoCs or less that actually use that language feature.

Let's be real here: when is renaming a function argument the only change that happens to a function signature? If the argument's name and semantics change, the function's semantics change as well. This means that you need to review all your call sites anyway. And in my experience, even in large code bases, only a small section of the code is called from so many places that this is onerous. These are the same pieces of code that calcify into near-immutability anyway, because the slightest change is going to break something somewhere else, anyway.

I'll just suggest a simple canary here: C# is a popular language and a lot has been written about it. How easy is it to find a statement that complains about the usage of named function arguments?
June 07, 2019
On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
> Languages like python that uses kwargs don't expose the names of all parameters.  They are able to pick and choose which parameters should be named.  This allows them to keep that layer of protection/encapsulation for the parameters where the name doesn't matter to the caller, just like when you have private fields where the name doesn't matter to an outside component.

Point of fact: python allows any parameter to be passed by name, not just kwargs:

    def f(x, y):
      return x - y

    print(f(y=2, x=5)) # prints "3"

The only languages I'm aware of with named arguments that require parameters to be explicitly marked as named in the function definition are Common Lisp [1] and Scheme [2]. In these languages, named parameters are entirely distinct from positional parameters--named parameters may only be passed by name, and positional parameters may only be passed by position.

[1] https://ccrma.stanford.edu/courses/220b-winter-2005/topics/commonlisp/arguments.html
[2] https://srfi.schemers.org/srfi-89/srfi-89.html
June 07, 2019
On Friday, 7 June 2019 at 15:28:00 UTC, Gregor Mückl wrote:
> On Friday, 7 June 2019 at 15:15:40 UTC, Jonathan Marler wrote:
>> On Friday, 7 June 2019 at 12:09:51 UTC, Yuxuan Shui wrote:
>>> On Thursday, 6 June 2019 at 19:17:38 UTC, Jonathan Marler wrote:
>>>> [...]
>>>
>>> Where were you during the last community review? :)
>>>
>>> Last time literally _everyone_ is arguing against named parameters being opt-in, and that's why I removed the opt-in-ness (the @named attribute) from the DIP.
>>>
>>
>> I'm not actually sure if they should be opt-in. I'm pointing out the problem with them always being on. They way I suggested for them to be opt-in has 2 problems. One is that libraries will need to break compatibility with older compilers to enable them. Without opt-in, only the caller needs to do this. The second is that it users will have to wait for libraries to update before they can use the feature, and libraries may be hesitant to update to remain compatible with older compilers, at least for a while.
>>
>> I'm just pointing out a problem I see. We should all be aware of the problem. Whether or not the problem is a big deal or had a good solution is another question. I think it's a big deal, and we should solve it if we can.
>>
>
> C# has had named arguments for quite a while now without any way to opt in or opt out. If you want to name a function argument, you just do it. If it breaks, it breaks. I haven't seen breakage from that in practice, yet. Mostly, because people only use that syntax for complex functions that have long parameter lists or challenging parameter lists with 4 to 5 boolean parameters in row or something borderline insane like that. So, I'd say that it's in the ballpark of one in 1000 LoCs or less that actually use that language feature.
>

Maybe I am over-estimating the problem with exposing parameter names.  It was also pointed out that python actually does expose all it's parameter names, not just kwargs.

If people only use parameter names in cases where they make sense, then I agree that this is a non-issue.  By making it opt-in, you can guarantee that you're library won't be misused so you will still be free to change it without people complaining when you break their mis-use of your library. The less people mis-use the feature, the less of a problem it becomes.

I'd be curious to see how named parameters has affected development decisions for libraries in C#.  The Microsoft .NET Framework Libraries are pretty exhaustive, and once an API is in place, it usually never changes.  They usually only *ADD* new APIs and rarely change existing ones. I wonder if they had any issues with legacy parameter names that weren't necessarily consistent once they enabled named parameters for everything.  Something to look into.
June 07, 2019
On 2019-06-06 22:04, Walter Bright wrote:
> I'll reiterate what I wrote for DIP1020 https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1_325299.html#N325627 
> 
> 
> ---
> 
> Here's a much simpler proposal, based on the recognition that D already has
> named parameters:
> 
>     https://dlang.org/spec/struct.html#static_struct_init
> 
> and related:
> 
>     https://dlang.org/spec/hash-map.html#static_initialization
>     https://dlang.org/spec/arrays.html#static-init-static
> 
> The only additional syntax would be allowing the equivalent of
> https://dlang.org/spec/hash-map.html#static_initialization in the argument
> list.
> Assignment of arguments to parameters would work the same way as assignments to
> fields.

Related https://github.com/dlang/DIPs/pull/71.

> As for the semantics, given this constraint, nothing needs to be invented, just
> discovered as necessary behavior. Consider:
> 
>      void snoopy(T t, int i, S s);     // A
>      void snoopy(S s, int i = 0; T t); // B
> 
> and calling it:
> 
>      S s; T t; int i;
>      snoopy(t, i, s); // A
>      snoopy(s, i, t); // B
>      snoopy(s, t); // error, neither A nor B match
>      snoopy(t, s); // error, neither A nor B match
>      snoopy(s:s, t:t, i:i); // error, ambiguous
>      snoopy(s:s, t:t); // B
>      snoopy(t:t, s:s); // B
>      snoopy(t:t, i, s:s); // A
>      snoopy(s:s, t:t, i); // A
> 
> I.e. function resolution is done by constructing an argument list separately
> for
> each function before testing it for matching. Of course, if the parameter
> name(s) don't match, the function doesn't match. If a parameter has no
> corresponding argument, and no default value, then the function doesn't match.
> 
> I don't see much point in requiring the names, preventing use of names, nor
> aliasing them. This has never been an issue for struct initializers.
> 
> One nice thing about this is the { } struct initialization syntax can be
> deprecated, as S(a:1, b:2) can replace it, and would be interchangeable with
> constructor syntax, making for a nice unification. (Like was done for array
> initialization.)
> 
> One issue would be order of evaluation: would the arguments be evaluated in the
> lexical order of the arguments, or the lexical order of the parameters?
> 
> Rationale:
> 
> Although this supports reordering, the real reason for naming is so one can
> have
> a function with a longish list of parameters, each with a reasonable default,
> and the user need only supply the arguments that matter for his use case. This
> is much more flexible than the current method of putting all the defaults at
> the
> end of the parameter list, and defaulting one means all the rest get defaulted.
> 
> A secondary reason is (again) for a longish list of parameters, when the user
> finds himself counting parameters to ensure they line up, then named parameters
> can be most helpful.

This is similar to how it works in Ruby:

foo({ "asd" => 3 }) # pass a hash (associative array) to "foo"

It's also common to pass a symbol instead of a string when the valid keys are few:

foo({ :asd => 3 })

In a function call, when passing a hash, it's possible to drop the curly braces:

foo(:asd => 3)

In Ruby 1.9 they added syntax sugar constructing hashes with symbols as the keys:

foo({ asd: 3 })

Combining that with the possibility to drop the curly braces you basically get named arguments:

foo(asd: 3)

Note that in all these cases the hash corresponds to one parameter at the declaration site.

Then in Ruby 2.0, proper named arguments were added. This requires opt-in on the declaration site:

def foo(bar:, asd: 3)
end

Using the colon (:) on the declaration site requires the caller to supply the named arguments.

foo(1, 2) # error
foo(bar: 1, asd: 2) # ok

-- 
/Jacob Carlborg
June 07, 2019
On 6/7/2019 5:27 AM, Yuxuan Shui wrote:
> 1. (Clearly function overloading is affected, but) is name mangling also affected?

No.

> 2. What about declarations in .di files?

No.

> 3. What about function declarations with parameter names different from the definition?

The declaration the compiler sees is what matters.
June 07, 2019
On 6/7/2019 6:27 AM, Yuxuan Shui wrote:
> And how do you deal with:
> 
>      void func(Args...)(Args args);
> 
> ?


It doesn't make sense to use named parameters for arbitrary arguments of arbitrary types.
June 08, 2019
On 6/5/19 9:03 AM, Mike Parker wrote:
> This is the feedback thread for the second round of Community Review for DIP 1019, "Named Arguments Lite":
> 
> https://github.com/dlang/DIPs/blob/9c9cc39246de4c449fe1e6cb6b27f7e426ff1eb9/DIPs/DIP1019.md 

[initially posted in the wrong thread, pasting here for conformity]


Things that I think would make this DIP stronger:

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

(@Michael we need to make "Related Work" a required section.)

* The example with "CalculateProduct(values, 7, false, null);" in the rationale should be completed with the best-of-the-breed solution in the current D language, i.e. using Flag. Currently Flag is not being discussed at all and it should because it is a workaround to named parameters (however insufficient as the proposal might argue).

* The argument with repurposing argument is weak because code that doesn't use named parameters would be broken anyway, which makes the idea of repurposing parameters bad to start with. I suggest it be dropped, or mentioned later as a perk of named parameters.

* "The relevance of forward declarations will become clear later." -> "Section xyz clarifies the relevance of forward declarations."

* "Named arguments proposed by this DIP have no effect on the ordering of arguments in function calls." Related work will in all likelihood reveal that reordering arguments in large argument lists is a key advantage of named arguments. Not availing ourselves of that advantage is a serious issue that weakens the proposal. It must explain why it is not possible to allow reordering of arguments (or better yet work out the mechanics to allow it).

* "Named arguments proposed by this DIP do not allow default parameters to be skipped." Not sure what "skipped" means in context; I assume it means some defaulted arguments would be left unspecified and other following them would be specified with non-default values. My understanding is that this is another key advantage of named arguments in related work - typically complex functions with large argument lists like CreateWindow, CreateArchive etc. would have many arguments defaulted to reasonable values, which then the caller can pick and choose which to customize. I assume a large part of what makes Python APIs so friendly is this ability. The DIP should explain why this is not desirable or achievable for the D language (or again better yet make it just work).

* "Variadic arguments can be labeled with the name of the variadic parameter and a subscript." seems to have little value if there's only one variadic per function and all indexes must be specified in order. The DIP should explain why this feature (the index can be any compile-time expression... right?) is useful.

* "If a function is defined with some of its parameter names omitted, arguments to those parameters can labeled with an empty name." The utility of this should be explained.

* "This seems to be the biggest concern among people who are against named arguments." This is vague and nonscientific and has no place in a DIP. Who are those (does it even matter), where are the relevant exchanges, how did the author arrive at the conclusion that this is the biggest concern. The concern should be discussed at face value and if appropriate rebutted soundly with an analysis of the tradeoff (I assume it's not "all bad" vs "all good" but more like pros and cons).

* "Allow calling the same function with a different set of parameter names." The advantage of this seems to be backward compatibility, but it endorses a technique that is questionable in the first place.

* "This DIP does not prohibit future proposals for adding parameter reordering, partially-specified parameter names with reordering, named template parameters, omission of default arguments by using named arguments, and other similar things." The problem here is that all of these (easily anticipated as desirable) weaken the DIP by their absence from it.
June 08, 2019
On Friday, 7 June 2019 at 13:25:21 UTC, Yuxuan Shui wrote:
> On Wednesday, 5 June 2019 at 15:41:08 UTC, Kagamin wrote:
>> Remove the variadic functions section. That's a tuple parameter, not variadic, and should use (future) tuple syntax.
>
> Are you suggesting we will be forced to call
>
>     void func(Args...)(int, Args);
>
> Like this:
>
>     func(1, (1,2,3));
>
> In the future?

I mean syntax of named arguments, syntax of positional arguments doesn't change.