August 26, 2019
struct S { int a, b, c, d = 7; }
S w = { c:1, a:1, 3 };

I don't even know if this result is contrived. Maybe it's trivial?
August 26, 2019
Formally: struct initializer syntax is very powerful and has only one restriction, but the consequence of this power is lack of redundancy with the usual consequences.
August 26, 2019
On Saturday, 24 August 2019 at 01:09:48 UTC, Jonathan M Davis wrote:
> Personally, I'm against named arguments in general. They make the parameter names part of the API, which adds another set of names that you have to get right up front and which will be bike-shedded to death. The _only_ use case IMHO where they add any real value is when you have a long parameter list where most of the parameters having default arguments. Such functions are usually a bad design, so I'm fine with not having named arguments in the language to make such designs seem more reasonable. If your parameter list is long enough that it doesn't work to go by the order of the arguments, then you already have a problem. But if we're going to add named arguments, then IMHO, the rare case where it actually makes sense to have a lot of parameters with default arguments is what named arguments are there to solve. So, if the DIP can't solve that, then IMHO, it's just making the language worse to no benefit.

+1.

Matheus.
August 26, 2019
On Monday, 26 August 2019 at 14:47:01 UTC, Kagamin wrote:
> struct S { int a, b, c, d = 7; }
> S w = { c:1, a:1, 3 };
>
> I don't even know if this result is contrived. Maybe it's trivial?

of course its trivial, this is "D Rorschach test".
even more:
u can get green care-De belt if u can answer how will be initialized struct just look at 20 samples.
and u will get brown care-De belt when u can say same for overloaded functions.

everything has already been decided.
u can write like that, there won’t be any errors, just don’t write like that.
August 26, 2019
On Monday, August 26, 2019 8:18:21 AM MDT Kagamin via Digitalmars-d wrote:
> On Saturday, 24 August 2019 at 01:09:48 UTC, Jonathan M Davis
>
> wrote:
> > Personally, I'm against named arguments in general. They make the parameter names part of the API, which adds another set of names that you have to get right up front and which will be bike-shedded to death.
>
> Errors in function names happen too.

My point is that adding named arguments results in even more bikeshedding over names. We already have more than enough trouble with that over function names and type names in APIs. I don't want parameter names to be added to that. I don't want to have to care about how good the parameter names are or have to worry about breaking anyone's code when changing a parameter name. And since parameter names have never actually been part of the API in D, existing parameter names were not selected with the idea that they would be used by anyone other than the function itself. For instance, if we had named arguments, all of a sudden, we'd have issues with whether range-based used range, r, or some other name entirely for the range that they're consuming or wrapping. Phobos is not at all consistent about that - and it hasn't needed to be. If we added named arguments, that sort of thing would then matter. I don't want to have to deal with any of that.

> > The _only_ use case IMHO where they add any real value is when you have a long parameter list where most of the parameters having default arguments.
>
> Another use case is replacing the Flag thing. When a function has only one parameter and it's has primitive type, names argument will have merit.

Honestly, I don't think that Flag is worth much. In most cases, a simple bool would do the job just fine. You already have to know what the parameter is for to use the function anyway. In general, it seems to me like Flag is an excuse for people to think that they don't need to actually read the documentation. And the cases where you really get value out of an enum are generally the cases where you need more than just true and false. I know that some folks like Flag, but in general, I think that it's an unnecessary complication.

- Jonathan M Davis



August 26, 2019
On Monday, 26 August 2019 at 21:48:42 UTC, Jonathan M Davis wrote:
> I know that some folks like Flag, but in general, I think that it's an unnecessary complication.

I'm all about information at a glance. The more you are able to understand a line of code without looking at the surrounding lines, the clearer and easier to maintain that code is.

Simple example:

void DoSomething( bool Multithreaded, bool Logging );

Which, when invoked using literals, looks like:

DoSomething( true, false );

Yech. That's where flags comes in handy:

DoSomething( Multithreaded.Yes, Logging.No );

Bam. Far more readable at a glance. Named parameters remove the template instantiations from that example:

DoSomething( Multithreaded : true, Logging : false );

At the cost of needing to do a "find and replace in files" when upgrading compilers/libraries if a parameter name changes, in both cases you have far more readable code.

Besides. Didn't the DIP here include a mechanism for handling parameter renaming and forwarding? And marking parameter name sets as deprecated?
August 26, 2019
On 8/26/2019 7:47 AM, Kagamin wrote:
> struct S { int a, b, c, d = 7; }
> S w = { c:1, a:1, 3 };
> 
> I don't even know if this result is contrived. Maybe it's trivial?

It initializes to:

    c = 1
    a = 1
    b = 3
    d = 7
August 26, 2019
On Monday, August 26, 2019 4:18:51 PM MDT Ethan via Digitalmars-d wrote:
> On Monday, 26 August 2019 at 21:48:42 UTC, Jonathan M Davis wrote:
> > I know that some folks like Flag, but in general, I think that it's an unnecessary complication.
>
> I'm all about information at a glance. The more you are able to understand a line of code without looking at the surrounding lines, the clearer and easier to maintain that code is.
>
> Simple example:
>
> void DoSomething( bool Multithreaded, bool Logging );
>
> Which, when invoked using literals, looks like:
>
> DoSomething( true, false );
>
> Yech. That's where flags comes in handy:
>
> DoSomething( Multithreaded.Yes, Logging.No );
>
> Bam. Far more readable at a glance. Named parameters remove the template instantiations from that example:
>
> DoSomething( Multithreaded : true, Logging : false );
>
> At the cost of needing to do a "find and replace in files" when upgrading compilers/libraries if a parameter name changes, in both cases you have far more readable code.

That particular use of Flag is more valuable than many uses of it, because you actually have multiple arguments, whereas in most cases, only one Flag gets used. Ultimately though, unless there are a lot of parameters (which is usually bad function design), I think that the benifit is minimal.

I get the impression that many people just want to use Flag or named arguments as an excuse to avoid even reading the function's documentation. I agree that it's great if what a function call does is obvious at a glance, but I also think that it's dangerous to assume that you know just by looking at the function call. If you don't actually read the function's documentation, then it's easy to end up making bad assumptions about what it does.

Naming is important and having the function's name be representative of what it does makes it far easier to remember what it's supposed to do, and it does help see what code probably does at a glance when you haven't read the docs yet, but ultimately, you need to read the docs, and when people argue for named arguments, it frequently seems like they want to be able to just look at a piece of code and know exactly what it does without ever reading the docs (heck, many people seem to want that based purely off of how a function is named, which is part of why there's a ton of bikeshedding over function names). Once you've actually read the docs and are familiar with what the functions do, then the names serve to remind you rather than inform you, and the need to label everything is far less. But for a lot of arguments, you have the names of the variables being passed anyway, and if anyone really wants to label what a boolean literal is for, they can always use a comment in-place.

> Besides. Didn't the DIP here include a mechanism for handling parameter renaming and forwarding? And marking parameter name sets as deprecated?

That doesn't change the fact that the parameter names are then part of the API and are yet another set of names that are going to be the subject of bikeshedding and are going to be something that you then can't simply change without worrying about breaking code. Having a way to deprecate names makes it possible to change stuff over time, but it's still far better IMHO to not have the names be part of the API in the first place.

For me personally, I think that having to deal with parameters becoming part of the API and how that adds to the difficulties that already exist around naming functions and types in public APIs is enough of a problem that it outweighs any of the supposed benefits that named arguments provide - even more so when it frequently seems like the reasons behind wanting named arguments relate to making badly designed functions easier to deal with (e.g. having tons of parameters for a function) or relate to folks looking to avoid reading documentation.

- Jonathan M Davis



August 27, 2019
I feel this DIP is bashed a bit too heavily here.

I do share the concern of most people that the DIP should include at least some argument reordering. My impression is that you removed the reordering you had at community review one to avoid the `@named` parameter, that was not well received by some.

Unfortunately, preventing all argument reordering just does not work. Like many have said, such named parameters would be tedious and likely unpopular to use. But there is another problem too, one that had you to include argument reordering in the draft stage, I believe:

´´´
foo(int a, int b)
foo(double b, int a)
´´´

If the dip will consider argument reordering, a call `foo(a:3, b:3)` can be specified as an ambiguous call, triggering a compiler error. However, if your DIP as now is implemented, that call would bind to the first function, preventing ambiguity checking later on, without core breakage. As long as you have this problem, it defeats the purpose of "less-is-more" philosophy.

No, you need at least some form of argument reordering. It could be along the lines of what Walter proposed, or something like Rikki's base idea (named parameters being separated from unnamed ones on API, and overload only by unnamed params).

This all being said, you actually wrote a DIP. It's easy to bash the concept when one has to consider only the concept, not corner cases and specification. I don't agree with Andrei: writing a DIP with argument reordering would be a major undertaking, just as difficult and very possibly more so than this one with all the corner cases to consider. We can't except to easily find a champion for that.

Perhaps this DIP can be used incrementally after all, just not by including it to D as-is. If Rikki's DIP won't get through, and if someone wants to write a real DIP from Walter's proposal, a lot of the details are already ready if you paper is used as base. Even better, if you don't want to do it yourself, you can abandon the DIP. That way someone can just stick argument reordering in and go straight to community review past the draft queue (Or can they? Mike?).
August 27, 2019
On Saturday, 24 August 2019 at 06:17:07 UTC, Walter Bright wrote:
> On 8/23/2019 10:00 PM, a11e99z wrote:

by the way
can we use named arguments for struct literals or only for defined constructors?
https://dlang.org/spec/struct.html#struct-literal