January 24, 2016
On 2016-01-24 11:14, default0 wrote:

> As for this DIP I don't know - it seems to be well-thought-out, albeit
> with a focus on ease of implementation rather than usefulness for a
> language user, so I don't really have a conclusive opinion on that.

It's focused on having a realistic chance of being accepted.

-- 
/Jacob Carlborg
January 24, 2016
On 2016-01-24 12:20, Gary Willoughby wrote:

> This can be done using templates and Flag is not an ugly hack!

It's one of the most ugly things I've seen in D.

-- 
/Jacob Carlborg
January 24, 2016
On 2016-01-23 14:19:03 +0000, Jacob Carlborg <doob@me.com> said:

> This is mostly to prevent ugly hacks like Flag [1].
> 
> http://wiki.dlang.org/DIP88
> 
> [1] https://dlang.org/phobos/std_typecons.html#.Flag

Interesting.

This is somewhat similar to an experiment of mine from 5 years ago. My implementation was a bit of a hack, but my intent was to have a proof of concept done quickly. All arguments were considered optionally named in this experiment (there was no syntax to enable this in the function prototype). Also it didn't extend to templates arguments.

You can my discussion with Walter about it here:
https://github.com/michelf/dmd/commit/673bae4982ff18a3d216bc1578f50d40f4d26d7a

Mixing reordering with overloading can become quite complicated. It's good that you leave that out at first. Adding reordering should be left as a separate task for later, if desired. Small steps.

Have you considered supporting separate variable names? Like this:

	void login(string username: name, string password:) {
		writeln(name ~ ": " ~ password);
	}

where an identifier following the colon, if present, would be the name of the variable inside the function. That way you can use a shorter variable when it makes sense to do so. Or change the variable name without affecting the API.

-- 
Michel Fortin
http://michelf.ca

January 24, 2016
On 2016-01-23 14:19:03 +0000, Jacob Carlborg <doob@me.com> said:

> This is mostly to prevent ugly hacks like Flag [1].
> 
> http://wiki.dlang.org/DIP88
> 
> [1] https://dlang.org/phobos/std_typecons.html#.Flag

On further thought, how do you make templates with specialization take named arguments?

	template TFoo(T)        { ... } // #1
	template TFoo(T : T[])  { ... } // #2
	template TFoo(T : char) { ... } // #3

My guess would be this:

	template TFoo(T:)        { ... } // #1
	template TFoo(T: : T[])  { ... } // #2
	template TFoo(T: : char) { ... } // #3

... but it makes the declaration a bit strange.

-- 
Michel Fortin
http://michelf.ca

January 24, 2016
On 2016-01-24 14:16, Michel Fortin wrote:

> Have you considered supporting separate variable names? Like this:
>
>      void login(string username: name, string password:) {
>          writeln(name ~ ": " ~ password);
>      }

No, not really.

-- 
/Jacob Carlborg
January 24, 2016
On 2016-01-24 14:24, Michel Fortin wrote:

> On further thought, how do you make templates with specialization take
> named arguments?
>
>      template TFoo(T)        { ... } // #1
>      template TFoo(T : T[])  { ... } // #2
>      template TFoo(T : char) { ... } // #3
>
> My guess would be this:
>
>      template TFoo(T:)        { ... } // #1
>      template TFoo(T: : T[])  { ... } // #2
>      template TFoo(T: : char) { ... } // #3
>
> ... but it makes the declaration a bit strange.

Yes. Rule 7 covers that. There's also an example showing the syntax, search for "Template specialization with named parameter". Yes, it does look a bit strange.

-- 
/Jacob Carlborg
January 24, 2016
On Sun, 24 Jan 2016 13:04:20 +0100, Jacob Carlborg wrote:
> On 2016-01-23 19:27, Chris Wright wrote:
>> I'd also add that this proposal doesn't affect UFCS.
> 
> How would it affect UFCS?

It shouldn't. However, it is another way to pass function arguments, so for thoroughness it would be better to mention it.

>> I'll note that parameter names are already part of documentation, and they're already the only parameter documentation you're guaranteed to have.
> 
> Currently it's possible to change a parameter name without the call site needing any change. Documentation has nothing to do with that.

I mentioned this because it strongly encourages people to use appropriate and descriptive names when writing functions. Appropriate and descriptive names are less likely to need to change. This doesn't eliminate your point that, today, people can change argument names and be guaranteed not to break client code.

>> Given this trend, people will be confused if they can't reorder named parameters. The main benefit of not letting people reorder things is reducing the amount of work *you* need to do when creating this DIP (and the amount others need to do when implementing it).
> 
> No. The only reason why that is not allowed is to have a greater chance of the DIP being accepted. The language would be even more complicated if it was possible to reorder the arguments. It's a benefit for the users if the language is simpler.

There's more chance of it being rejected as not sufficiently beneficial and less chance of it being rejected as too much complexity. But let's look at that complexity angle. What sort of complexity do we want to eliminate?

There was recently a post that made the point that an hour of time from a compiler developer making something easier and saving each user an hour of time is a huge productivity gain in all. So we want to reduce complexity for language users, and making a more complex compiler is only problematic insofar as it makes the compiler slower or buggier.

All else being equal, adding constraints generally adds complexity and removing them generally reduces complexity. Any constraint we add has to pay for its complexity somehow. Having to remember parameter order while specifying unambiguously which parameter I'm trying to use is an added constraint and therefore added complexity. It gives nothing in return.

Since absolutely no language has previously required named arguments to retain the same order they're declared in, apparently everyone else disagrees that the feature is too complex. Even Python, which is specifically aimed at beginners, allows reordering.

The most similar thing to named parameters that's already in D is struct initializers. These do not require that you order the struct member initializers in the same order as the related fields are declared. This means that users have to remember two sets of similar syntax that function differently in an important way. That's added complexity within D.

It's a benefit to users if things work in a familiar way. I haven't been able to find a language that works in the way you propose, so for people familiar with other languages, this DIP results in confusing behavior. That's added complexity across languages. And since D doesn't have the same market penetration that Java or Javascript have, it's extremely difficult for a person to be familiar only with D.

>> Document how it's supposed to handle optional parameters
> 
> It's already documented.

I missed that. My apologies.

Your proposal says this works:

  void foo(int a: = 3, int b: = 4);
  foo();
  foo(a: 5, b: 6);

But we can conclude that the following is not allowed:

  foo(b: 6);

This is because it's not legal to change the order of arguments by specifying names, and you must supply optional parameters of the same type in order, without omitting any, if you don't have names. Your proposal did not involve any special casing here.

Is this what you intended? If so, please document it so other reviewers don't have to wonder.
January 24, 2016
On Sun, 24 Jan 2016 10:14:53 +0000, default0 wrote:
> So given this method:
> void M(int a, int b = 1, int c = 2, int d = 3, int e = 4, int f =
> 5, int g = 6, int h = 7, int i = 8)
> {
> }
> 
> You prefer calling it this way:
> M(5, 1, 2, 3, 4, 5, 6, 7, 23);
> As opposed to:
> M(5, i: 23);

Actually, the proposal doesn't allow the latter. It explicitly doesn't allow you to change the order of parameters and says nothing about allowing this as a special case, so you would have to write it as:

M(5, b: 1, c: 2, d: 3, e: 4, f: 5, g: 6, h: 7, i: 23);

Which is slightly more readable but still a nightmare for maintainability.
January 24, 2016
On Sun, 24 Jan 2016 08:16:35 -0500, Michel Fortin wrote:

> Have you considered supporting separate variable names? Like this:
> 
> 	void login(string username: name, string password:) {
> 		writeln(name ~ ": " ~ password);
> 	}

You mean:

  void login(string username:, string password:) {
    alias name = username;
    writeln(name, ": ", password);
  }
January 24, 2016
On Sun, 24 Jan 2016 11:20:20 +0000, Gary Willoughby wrote:

> On Saturday, 23 January 2016 at 14:19:03 UTC, Jacob Carlborg wrote:
>> This is mostly to prevent ugly hacks like Flag [1].
>>
>> http://wiki.dlang.org/DIP88
> 
> "A new syntax is added to be used when declaring a function that should be callable with named parameters:"
> 
> Please, no more new syntax!
> 
> This can be done using templates and Flag is not an ugly hack!

Okay, but only part of this has to do with booleans. Taking your proposal to its logical conclusion, you're saying I should write:

alias Typedef!(string, "key") Key;
alias Typedef!(string, "startDocumentID") StartDocumentID;
alias Typedef!(ulong, "limit") Limit;
alias Typedef!(ulong, "resultsPerPage") ResultsPerPage;

CouchPaginatedRange query(
  Key key = Key(""),
  StartDocumentID startID = StartDocumentID(""),
  Limit limit = Limit(ulong.max),
  ResultsPerPage resultsPerPage = ResultsPerPage(50),
  Flag!"includeDocuments" includeDocuments = No.includeDocuments) {}

query(Key("foo"), Yes.includeDocuments);

This is an interesting proposal, but I'll only ever consider it if Walter says we're never getting sparse named arguments.