February 09, 2020
On Sunday, 9 February 2020 at 01:47:35 UTC, Jon Degenhardt wrote:
> On Sunday, 9 February 2020 at 01:07:03 UTC, Adam D. Ruppe wrote:
>> [...]
>
> Probably not, but let me give some thoughts and ask a clarifying question.
>
> Main thing - As a pragmatic matter, I'd expect it to be much more likely that named argument invocation would be a source of breakage than usage arising from introspection.
>
> Related - There is significant difference between parameter names being public and having the names be sources of backward compatibility in function calls.
>
> Now my question - I know function parameters names can be retrieved by type introspection. What I don't know is the ways those names can be used such that programs can break if a parameter names change. Can you give some examples?

vibe.d uses parameter names to generate REST api bindings
see: https://vibed.org/docs#rest-interface-generator
February 09, 2020
On 2/8/20 11:10 PM, Jon Degenhardt wrote:
> For Phobos this would be my expectation as well. I'm admittedly thinking of project environments with meaningful size teams more than the standard library of a major programming language. Environments where there is a fair bit of code in earlier stages of development and subject to more evolution.

I think the evolution goes like this:

void foo(int tmpName);

...

// all callers:

foo(5); // didn't use named parameters because I have no idea what "tmpName" means

now, we evolve foo:

void foo(int milliseconds);

Now, all calls still work because nobody used the bad name as "documentation". New calls now use the name sometimes because it's helpful. My point is simply that the name itself is going to not require, but probably result in, people using or not using the name. Bad names naturally aren't going to get name usage, because they suck and aren't helpful. Good names are.

I understand though, there are possible bikeshed problems here. For example, someone who implements foo might be tired of typing out "milliseconds" and change the parameter name to "ms". Now that person has to worry about what happens for callers. So instead he has to leave milliseconds in the name, and create a temporary ms in his function. At that point, you have to weigh how important it is to change that parameter name against the breakage that might occur. How much does it cost to repaint the shed? Might not be worth it.

Note that Swift (which has parameter names as part of the function name) has a mechanism to deal with this.

A function in swift looks like:

func foo(a : int) -> Void

You MUST call the function with foo(a: 5). foo(5) doesn't work.

But you can name the parameter to the outside and name the parameter differently on the inside:

func foo(milliseconds a: int) -> Void

Now, you call the function with foo(milliseconds: 5), and inside the function, the parameter is named 'a'.

Not sure this could be doable in D. But for a main language that started out with significant naming of parameters (inheriting this from objective-C), it's a good place to look for inspiration here.

-Steve
February 09, 2020
On Sunday, 9 February 2020 at 18:32:45 UTC, Steven Schveighoffer wrote:
> Now, you call the function with foo(milliseconds: 5), and inside the function, the parameter is named 'a'.

We can always just `alias a = milliseconds;` inside the function.

Changing inside alone is easy, though changing the outside one is a bit trickier. We can't overload on name alone so no way to use function-level `deprecated` messages. But maybe a pragma or deprecated alias syntax on names could be enough.

Users changing is easy too, just the lib implementer wanting to provide some range of compatibility would probably want the deprecated alias to keep working for a while. So we might consider adding such a thing.

void foo(int milliseconds deprecated alias ms) {}

wow ugly syntax lol but i think the grammar would allow that and now the param has two names for inside and outside and gives a place for us to put a message.

but i kinda suggest just not worrying about it until experience proves this is a real problem that needs to be solved.
February 09, 2020
On Sunday, 9 February 2020 at 18:32:45 UTC, Steven Schveighoffer wrote:
> But you can name the parameter to the outside and name the parameter differently on the inside:
>
> func foo(milliseconds a: int) -> Void
>
> Now, you call the function with foo(milliseconds: 5), and inside the function, the parameter is named 'a'.
>
> Not sure this could be doable in D. But for a main language that started out with significant naming of parameters (inheriting this from objective-C), it's a good place to look for inspiration here.
>
> -Steve

You can alias the parameter inside the function:

void foo(int milliseconds)
{
    alias ms = milliseconds;
    // Use 'ms' from here on
    // ...
}
February 09, 2020
On 2/9/20 1:45 PM, Adam D. Ruppe wrote:
> On Sunday, 9 February 2020 at 18:32:45 UTC, Steven Schveighoffer wrote:
>> Now, you call the function with foo(milliseconds: 5), and inside the function, the parameter is named 'a'.
> 
> We can always just `alias a = milliseconds;` inside the function.
> 
> Changing inside alone is easy, though changing the outside one is a bit trickier. We can't overload on name alone so no way to use function-level `deprecated` messages. But maybe a pragma or deprecated alias syntax on names could be enough.
> 
> Users changing is easy too, just the lib implementer wanting to provide some range of compatibility would probably want the deprecated alias to keep working for a while. So we might consider adding such a thing.
> 
> void foo(int milliseconds deprecated alias ms) {}
> 
> wow ugly syntax lol but i think the grammar would allow that and now the param has two names for inside and outside and gives a place for us to put a message.
> 
> but i kinda suggest just not worrying about it until experience proves this is a real problem that needs to be solved.

Agree with all of this.

-Steve
February 09, 2020
On 2/8/2020 4:56 PM, Jon Degenhardt wrote:
> That said, having parameter names automatically become part of a function's API is a meaningful downside. (Specifically, that a parameter name cannot be changed without risk of breaking existing callers.)

Note that D already has "named parameters" for struct initializers. That means, for example, that the names of the struct field cannot be changed without breaking any initializer relying on it.

I've never heard a single comment about this, let alone any complaint, nor any indication that anyone's code broke.
February 09, 2020
On 2/9/2020 10:32 AM, Steven Schveighoffer wrote:
> Not sure this could be doable in D. But for a main language that started out with significant naming of parameters (inheriting this from objective-C), it's a good place to look for inspiration here.

Since parameter names are not part of the name mangling, you can do things like:

  ---- A.di
  void foo(int x);

  ---- A.d
  void foo(int y) { ... }

And, of course, you can also do:

  ---- A.di
  void foo(int);

  ---- A.d
  void foo(int y) { ... }

February 09, 2020
On Sunday, 9 February 2020 at 19:45:20 UTC, Walter Bright wrote:
> On 2/8/2020 4:56 PM, Jon Degenhardt wrote:
>> That said, having parameter names automatically become part of a function's API is a meaningful downside. (Specifically, that a parameter name cannot be changed without risk of breaking existing callers.)
>
> Note that D already has "named parameters" for struct initializers. That means, for example, that the names of the struct field cannot be changed without breaking any initializer relying on it.
>
> I've never heard a single comment about this, let alone any complaint, nor any indication that anyone's code broke.

struct A {
   int foo;
}

struct A {
    int bar; // renamed from foo
    deprecated alias foo = bar;
};


False equivalency, you have many tools at your disposal to deal with this for structs.


Also found a bug.

A a = { foo: 10 }; // no deprecation warning, when foo is the deprecated alias
February 09, 2020
On 2/9/2020 11:51 AM, Arine wrote:
> Also found a bug.

Please report all bugs to bugzilla.
February 09, 2020
On 2/9/2020 11:51 AM, Arine wrote:
> struct A {
>     int foo;
> }
> 
> struct A {
>      int bar; // renamed from foo
>      deprecated alias foo = bar;
> };
> 
> 
> False equivalency, you have many tools at your disposal to deal with this for structs.


C has it, too. Never heard a single complaint about it, either.

https://en.cppreference.com/w/c/language/struct_initialization