[Idea] Omit argument labels from the call site when the argument is the same as the label


(Kenny Leung) #1

Hi All.

I’m just throwing this out there.

often when I write Objective-C, my method calls end up looking like this:

[you doYourThingWithThis:this that:that these:these those:those other:other];

This reads poorly and requires extra typing. It would be nice if the compiler just assumed that when no label is given, the label is the same as the argument name. The code would be just as understandable (more) than if the argument labels were actually there.

In Swift, this:

you.doYourThingWithThis(this, that:that, these:these, those:those, other:other)

becomes

you.doYourThingWithThis(this, that, these, those, other)

However, if you are the type that likes to name your variables a,b,c,d, no harm done, since then labels would be required, and it would still read OK

you.doYourThingWithThis(a, that:b, these:c, those:d, other:e)

-Kenny


(Alex Hoppen) #2

I don’t think it is possible to implement this without major changes to the way function overloads are selected.

Consider the following example with where there are multiple functions that can print a Double (yes, the external arguments could be put in the function’s name, but I hope it shows my point):

func myPrint(number: Double) { }
func myPrint(withTwoDecimals number: Double) { }
func myPrint(withThreeDecimals number: Double) { }

Currently all three of these functions have different signatures. If your syntax would be implemented in Swift, then

myPrint(withTwoDecimals)

would be ambiguous.

Defaulting to the function without external parameter names in case of ambiguity isn’t an option because then the call would change its behaviour the moment a library adds myPrint(number: Double) in addition to the other functions. This is definitely not desirable! The same applies for defaulting to the function with the external parameter name.

I don’t like leaving the function call ambiguous because then the only way to call myPrint(number: Double) would be to change the name of the variable. The name of any variable should by private and therefore not have any effect on how the function is called. (Also think about functions where there is basically only one proper way to name a variable, like x for coordinates. You would have to rename the variable which leads to less descriptive variable names).

Thus, the only way to resolve this issue IMO would be to say that the signatures myPrint(number: Double) and myPrint(withTwoDecimals number: Double) are identical. Then, however, the signatures of myPrint(withTwoDecimals number: Double) and myPrint(withThreeDecimals number: Double) would need to be equivalent as well, which seriously limits the way functions can be overloaded in Swift. I don’t think that the improved syntax is worth paying with the this expressiveness of function overloads.

- Alex

···

On 07 Feb 2016, at 20:45, Kenny Leung via swift-evolution <swift-evolution@swift.org> wrote:

Hi All.

I’m just throwing this out there.

often when I write Objective-C, my method calls end up looking like this:

[you doYourThingWithThis:this that:that these:these those:those other:other];

This reads poorly and requires extra typing. It would be nice if the compiler just assumed that when no label is given, the label is the same as the argument name. The code would be just as understandable (more) than if the argument labels were actually there.

In Swift, this:

you.doYourThingWithThis(this, that:that, these:these, those:those, other:other)

becomes

you.doYourThingWithThis(this, that, these, those, other)

However, if you are the type that likes to name your variables a,b,c,d, no harm done, since then labels would be required, and it would still read OK

you.doYourThingWithThis(a, that:b, these:c, those:d, other:e)

-Kenny

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tino) #3

In another discussion, I proposed to make labels optional (call-side only) as long as they are not needed to choose the right method — but as there was no positive feedback from core, I didn't pursue further on this (although I still think it would be a good move, moving the whole burden of when to have labels and when to skip them out of the language itself)


(Kenny Leung) #4

What if the compiler forced you to disambiguate by writing

myPrint(_:withTwoDecimals)

if you wanted to call "func myPrint(number: Double) { }”

-Kenny

···

On Feb 7, 2016, at 12:41 PM, Alex Hoppen <alex@ateamer.de> wrote:

I don’t think it is possible to implement this without major changes to the way function overloads are selected.

Consider the following example with where there are multiple functions that can print a Double (yes, the external arguments could be put in the function’s name, but I hope it shows my point):

func myPrint(number: Double) { }
func myPrint(withTwoDecimals number: Double) { }
func myPrint(withThreeDecimals number: Double) { }

Currently all three of these functions have different signatures. If your syntax would be implemented in Swift, then

myPrint(withTwoDecimals)

would be ambiguous.

Defaulting to the function without external parameter names in case of ambiguity isn’t an option because then the call would change its behaviour the moment a library adds myPrint(number: Double) in addition to the other functions. This is definitely not desirable! The same applies for defaulting to the function with the external parameter name.

I don’t like leaving the function call ambiguous because then the only way to call myPrint(number: Double) would be to change the name of the variable. The name of any variable should by private and therefore not have any effect on how the function is called. (Also think about functions where there is basically only one proper way to name a variable, like x for coordinates. You would have to rename the variable which leads to less descriptive variable names).

Thus, the only way to resolve this issue IMO would be to say that the signatures myPrint(number: Double) and myPrint(withTwoDecimals number: Double) are identical. Then, however, the signatures of myPrint(withTwoDecimals number: Double) and myPrint(withThreeDecimals number: Double) would need to be equivalent as well, which seriously limits the way functions can be overloaded in Swift. I don’t think that the improved syntax is worth paying with the this expressiveness of function overloads.

- Alex

On 07 Feb 2016, at 20:45, Kenny Leung via swift-evolution <swift-evolution@swift.org> wrote:

Hi All.

I’m just throwing this out there.

often when I write Objective-C, my method calls end up looking like this:

[you doYourThingWithThis:this that:that these:these those:those other:other];

This reads poorly and requires extra typing. It would be nice if the compiler just assumed that when no label is given, the label is the same as the argument name. The code would be just as understandable (more) than if the argument labels were actually there.

In Swift, this:

you.doYourThingWithThis(this, that:that, these:these, those:those, other:other)

becomes

you.doYourThingWithThis(this, that, these, those, other)

However, if you are the type that likes to name your variables a,b,c,d, no harm done, since then labels would be required, and it would still read OK

you.doYourThingWithThis(a, that:b, these:c, those:d, other:e)

-Kenny

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Alex Hoppen) #5

Looks OK to me, but still I don't like the fact that the name of a local variable can change whether or not this expression is ambiguous. Basically, the function call blocks certain variable names which the caller cannot use without escaping them using "_:". To me it feels like the function definition can introduce some kind of keyword and that seems weird to me. But that's of course a matter of taste.

- Alex

···

On 07 Feb 2016, at 23:06, Kenny Leung <kenny_leung@pobox.com> wrote:

What if the compiler forced you to disambiguate by writing

myPrint(_:withTwoDecimals)

if you wanted to call "func myPrint(number: Double) { }”

-Kenny

On Feb 7, 2016, at 12:41 PM, Alex Hoppen <alex@ateamer.de> wrote:

I don’t think it is possible to implement this without major changes to the way function overloads are selected.

Consider the following example with where there are multiple functions that can print a Double (yes, the external arguments could be put in the function’s name, but I hope it shows my point):

func myPrint(number: Double) { }
func myPrint(withTwoDecimals number: Double) { }
func myPrint(withThreeDecimals number: Double) { }

Currently all three of these functions have different signatures. If your syntax would be implemented in Swift, then

myPrint(withTwoDecimals)

would be ambiguous.

Defaulting to the function without external parameter names in case of ambiguity isn’t an option because then the call would change its behaviour the moment a library adds myPrint(number: Double) in addition to the other functions. This is definitely not desirable! The same applies for defaulting to the function with the external parameter name.

I don’t like leaving the function call ambiguous because then the only way to call myPrint(number: Double) would be to change the name of the variable. The name of any variable should by private and therefore not have any effect on how the function is called. (Also think about functions where there is basically only one proper way to name a variable, like x for coordinates. You would have to rename the variable which leads to less descriptive variable names).

Thus, the only way to resolve this issue IMO would be to say that the signatures myPrint(number: Double) and myPrint(withTwoDecimals number: Double) are identical. Then, however, the signatures of myPrint(withTwoDecimals number: Double) and myPrint(withThreeDecimals number: Double) would need to be equivalent as well, which seriously limits the way functions can be overloaded in Swift. I don’t think that the improved syntax is worth paying with the this expressiveness of function overloads.

- Alex

On 07 Feb 2016, at 20:45, Kenny Leung via swift-evolution <swift-evolution@swift.org> wrote:

Hi All.

I’m just throwing this out there.

often when I write Objective-C, my method calls end up looking like this:

[you doYourThingWithThis:this that:that these:these those:those other:other];

This reads poorly and requires extra typing. It would be nice if the compiler just assumed that when no label is given, the label is the same as the argument name. The code would be just as understandable (more) than if the argument labels were actually there.

In Swift, this:

you.doYourThingWithThis(this, that:that, these:these, those:those, other:other)

becomes

you.doYourThingWithThis(this, that, these, those, other)

However, if you are the type that likes to name your variables a,b,c,d, no harm done, since then labels would be required, and it would still read OK

you.doYourThingWithThis(a, that:b, these:c, those:d, other:e)

-Kenny

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Kenny Leung) #6

Hi Tino.

I think my idea is significantly different from yours. Making all labels optional feels more like a “reversion” of coding style to languages that don’t have argument labels. It would still let you call a function like this:

    you.doYourThingWithThis(a, b, c, d, e)

thus making your code harder to read.

I think making them optional only when the variable name is the same as the label does not take away from the reader understanding exactly which method is being referred to.

-Kenny

···

On Feb 8, 2016, at 9:31 AM, Tino Heth <2th@gmx.de> wrote:

In another discussion, I proposed to make labels optional (call-side only) as long as they are not needed to choose the right method — but as there was no positive feedback from core, I didn't pursue further on this (although I still think it would be a good move, moving the whole burden of when to have labels and when to skip them out of the language itself)