[Update + Commentary] SE-0111: Remove type system significance of function argument labels


(Chris Lattner) #1

Proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

Shortly after SE-0111 was accepted last week, several people newly noticed the proposal and started a discussion about how it appears to be a regression for closure parameters (e.g. callbacks) that could formerly carry labels, but are now not allowed to. These folks observed that it would be more expressive (and consistent with the rest of Swift) to allow parameter labels in function types, because the invocation site of a closure “should" be required to provide those labels. The core team has been following the discussion, agrees that this is a concern, and wants to update the community with a path forward.

The reality of the situation is that the current implementation of parameter labels in function types is inherently broken. Specifically, as one example, there is an implicit conversion from "(a: Int) -> Int” to “(Int) -> Int”. However, there is also an implicit conversion from "(Int) -> Int” to “(b : Int) -> Int”. This means that the compiler currently allows converting from “(a: Int) -> Int” to “(b: Int) -> Int”, which doesn’t make sense, introduces surprising behavior, introduces complexity into the compiler implementation, and is generally a problem. We do have one specific hack to prevent conversion of (e.g.) “(a : Int, b : Int) -> Void” to “(b : Int, a : Int) -> Void”, but this only triggers in specific cases. There are other more complex cases as well, e.g. when using generics "T<(a : Int)->Int>” cannot be considered compatible with "T<(b : Int)->Int>”.

These problems are what initially motivated SE-0111. However, given the feedback, the core team went back to the drawing board to determine whether: a) SE-0111 by itself is the right long term answer, b) whether there were alternate models that could solve the same problems in a different way, or c) whether SE-0111 was the right first step to "ultimate glory" in the field of closure parameter labels. After a long discussion, and many alternatives considered, the core team believes in c), that SE-0111 (with a minor modification) is the right step for Swift 3, because it paves the way for the right model over the long term.

----8<----

The specific revision requested by the core team to SE-0111 is that all “cosmetic” labels should be required to include an API name of _. For example, this would not be allowed:

   var op : (lhs : Int, rhs : Int) -> Int

instead, it should be spelled as:

   var op : (_ lhs : Int, _ rhs : Int) -> Int

With this change, we believe that we have paved the way for a purely additive proposal (and thus, post-Swift 3) that will restore the expressive capability of closures with parameter labels.

----8<----

Here is a sketch of how that would work, in two steps:

First, we extend declaration names for variables, properties, and parameters to allow *parameter names* as part of their declaration name. For example:

   var op(lhs:,rhs:) : (Int, Int) -> Int // variable or property.
   x = op(lhs: 1, rhs: 2) // use of the variable or property.

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op(lhs:,rhs:) : (Int, Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // use of the parameter
   }
   foo(opToUse: +) // call of the function

This will restore the ability to express the idea of a closure parameter that carries labels as part of its declaration, without requiring parameter labels to be part of the type system (allowing, e.g. the operator + to be passed into something that requires parameter labels).

Second, extend the rules for function types to allow parameter API labels *if and only if* they are used as the type of a declaration that allows parameter labels, and interpret them as a sugar form for providing those labels on the underlying declaration. This means that the example above could be spelled as:

   var op : (lhs: Int, rhs: Int) -> Int // Nice declaration syntax
   x = op(lhs: 1, rhs: 2) // Same as above

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op : (lhs: Int, rhs: Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // Same as above.
   }
   foo(opToUse: +) // Same as above.

These two steps will provide the simple and expressive design approach that we have now, without all of the problems that representing parameter labels in the type system introduces. The core team believes that the temporary regression in expressiveness is an acceptable loss for Swift 3, particularly given that this will have no impact on Cocoa or the standard library. In the case of Cocoa, recall that C and Objective-C don’t have parameter labels on their corresponding concepts (Blocks and C function pointers), and the higher order functions in the standard library should not require parameter labels either.

-Chris & the Core Team


Disambiguating imports
Automatically derive properties for enum cases
(David Hart) #2

:clap:

···

On 14 Jul 2016, at 06:47, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

Proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md
Shortly after SE-0111 was accepted last week, several people newly noticed the proposal and started a discussion about how it appears to be a regression for closure parameters (e.g. callbacks) that could formerly carry labels, but are now not allowed to. These folks observed that it would be more expressive (and consistent with the rest of Swift) to allow parameter labels in function types, because the invocation site of a closure “should" be required to provide those labels. The core team has been following the discussion, agrees that this is a concern, and wants to update the community with a path forward.

The reality of the situation is that the current implementation of parameter labels in function types is inherently broken. Specifically, as one example, there is an implicit conversion from "(a: Int) -> Int” to “(Int) -> Int”. However, there is also an implicit conversion from "(Int) -> Int” to “(b : Int) -> Int”. This means that the compiler currently allows converting from “(a: Int) -> Int” to “(b: Int) -> Int”, which doesn’t make sense, introduces surprising behavior, introduces complexity into the compiler implementation, and is generally a problem. We do have one specific hack to prevent conversion of (e.g.) “(a : Int, b : Int) -> Void” to “(b : Int, a : Int) -> Void”, but this only triggers in specific cases. There are other more complex cases as well, e.g. when using generics "T<(a : Int)->Int>” cannot be considered compatible with "T<(b : Int)->Int>”.

These problems are what initially motivated SE-0111. However, given the feedback, the core team went back to the drawing board to determine whether: a) SE-0111 by itself is the right long term answer, b) whether there were alternate models that could solve the same problems in a different way, or c) whether SE-0111 was the right first step to "ultimate glory" in the field of closure parameter labels. After a long discussion, and many alternatives considered, the core team believes in c), that SE-0111 (with a minor modification) is the right step for Swift 3, because it paves the way for the right model over the long term.

----8<----

The specific revision requested by the core team to SE-0111 is that all “cosmetic” labels should be required to include an API name of _. For example, this would not be allowed:

   var op : (lhs : Int, rhs : Int) -> Int

instead, it should be spelled as:

   var op : (_ lhs : Int, _ rhs : Int) -> Int

With this change, we believe that we have paved the way for a purely additive proposal (and thus, post-Swift 3) that will restore the expressive capability of closures with parameter labels.

----8<----

Here is a sketch of how that would work, in two steps:

First, we extend declaration names for variables, properties, and parameters to allow *parameter names* as part of their declaration name. For example:

   var op(lhs:,rhs:) : (Int, Int) -> Int // variable or property.
   x = op(lhs: 1, rhs: 2) // use of the variable or property.

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op(lhs:,rhs:) : (Int, Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // use of the parameter
   }
   foo(opToUse: +) // call of the function

This will restore the ability to express the idea of a closure parameter that carries labels as part of its declaration, without requiring parameter labels to be part of the type system (allowing, e.g. the operator + to be passed into something that requires parameter labels).

Second, extend the rules for function types to allow parameter API labels *if and only if* they are used as the type of a declaration that allows parameter labels, and interpret them as a sugar form for providing those labels on the underlying declaration. This means that the example above could be spelled as:

   var op : (lhs: Int, rhs: Int) -> Int // Nice declaration syntax
   x = op(lhs: 1, rhs: 2) // Same as above

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op : (lhs: Int, rhs: Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // Same as above.
   }
   foo(opToUse: +) // Same as above.

These two steps will provide the simple and expressive design approach that we have now, without all of the problems that representing parameter labels in the type system introduces. The core team believes that the temporary regression in expressiveness is an acceptable loss for Swift 3, particularly given that this will have no impact on Cocoa or the standard library. In the case of Cocoa, recall that C and Objective-C don’t have parameter labels on their corresponding concepts (Blocks and C function pointers), and the higher order functions in the standard library should not require parameter labels either.

-Chris & the Core Team

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


(Taras Zakharko) #3

Great!

This cleanly separates between the type and the name/signature! Simple and consistent. Thank you!

A clarification question: do i understand correctly that steps 2 and 3 will not be included in Swift 3 due time constraints?

— T

···

On 14 Jul 2016, at 06:47, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

Proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md
Shortly after SE-0111 was accepted last week, several people newly noticed the proposal and started a discussion about how it appears to be a regression for closure parameters (e.g. callbacks) that could formerly carry labels, but are now not allowed to. These folks observed that it would be more expressive (and consistent with the rest of Swift) to allow parameter labels in function types, because the invocation site of a closure “should" be required to provide those labels. The core team has been following the discussion, agrees that this is a concern, and wants to update the community with a path forward.

The reality of the situation is that the current implementation of parameter labels in function types is inherently broken. Specifically, as one example, there is an implicit conversion from "(a: Int) -> Int” to “(Int) -> Int”. However, there is also an implicit conversion from "(Int) -> Int” to “(b : Int) -> Int”. This means that the compiler currently allows converting from “(a: Int) -> Int” to “(b: Int) -> Int”, which doesn’t make sense, introduces surprising behavior, introduces complexity into the compiler implementation, and is generally a problem. We do have one specific hack to prevent conversion of (e.g.) “(a : Int, b : Int) -> Void” to “(b : Int, a : Int) -> Void”, but this only triggers in specific cases. There are other more complex cases as well, e.g. when using generics "T<(a : Int)->Int>” cannot be considered compatible with "T<(b : Int)->Int>”.

These problems are what initially motivated SE-0111. However, given the feedback, the core team went back to the drawing board to determine whether: a) SE-0111 by itself is the right long term answer, b) whether there were alternate models that could solve the same problems in a different way, or c) whether SE-0111 was the right first step to "ultimate glory" in the field of closure parameter labels. After a long discussion, and many alternatives considered, the core team believes in c), that SE-0111 (with a minor modification) is the right step for Swift 3, because it paves the way for the right model over the long term.

----8<----

The specific revision requested by the core team to SE-0111 is that all “cosmetic” labels should be required to include an API name of _. For example, this would not be allowed:

   var op : (lhs : Int, rhs : Int) -> Int

instead, it should be spelled as:

   var op : (_ lhs : Int, _ rhs : Int) -> Int

With this change, we believe that we have paved the way for a purely additive proposal (and thus, post-Swift 3) that will restore the expressive capability of closures with parameter labels.

----8<----

Here is a sketch of how that would work, in two steps:

First, we extend declaration names for variables, properties, and parameters to allow *parameter names* as part of their declaration name. For example:

   var op(lhs:,rhs:) : (Int, Int) -> Int // variable or property.
   x = op(lhs: 1, rhs: 2) // use of the variable or property.

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op(lhs:,rhs:) : (Int, Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // use of the parameter
   }
   foo(opToUse: +) // call of the function

This will restore the ability to express the idea of a closure parameter that carries labels as part of its declaration, without requiring parameter labels to be part of the type system (allowing, e.g. the operator + to be passed into something that requires parameter labels).

Second, extend the rules for function types to allow parameter API labels *if and only if* they are used as the type of a declaration that allows parameter labels, and interpret them as a sugar form for providing those labels on the underlying declaration. This means that the example above could be spelled as:

   var op : (lhs: Int, rhs: Int) -> Int // Nice declaration syntax
   x = op(lhs: 1, rhs: 2) // Same as above

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op : (lhs: Int, rhs: Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // Same as above.
   }
   foo(opToUse: +) // Same as above.

These two steps will provide the simple and expressive design approach that we have now, without all of the problems that representing parameter labels in the type system introduces. The core team believes that the temporary regression in expressiveness is an acceptable loss for Swift 3, particularly given that this will have no impact on Cocoa or the standard library. In the case of Cocoa, recall that C and Objective-C don’t have parameter labels on their corresponding concepts (Blocks and C function pointers), and the higher order functions in the standard library should not require parameter labels either.

-Chris & the Core Team

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


(Ben Rimmington) #4

Proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md
Shortly after SE-0111 was accepted last week, several people newly noticed the proposal and started a discussion about how it appears to be a regression for closure parameters (e.g. callbacks) that could formerly carry labels, but are now not allowed to. These folks observed that it would be more expressive (and consistent with the rest of Swift) to allow parameter labels in function types, because the invocation site of a closure “should" be required to provide those labels. The core team has been following the discussion, agrees that this is a concern, and wants to update the community with a path forward.

The reality of the situation is that the current implementation of parameter labels in function types is inherently broken. Specifically, as one example, there is an implicit conversion from "(a: Int) -> Int” to “(Int) -> Int”. However, there is also an implicit conversion from "(Int) -> Int” to “(b : Int) -> Int”. This means that the compiler currently allows converting from “(a: Int) -> Int” to “(b: Int) -> Int”, which doesn’t make sense, introduces surprising behavior, introduces complexity into the compiler implementation, and is generally a problem. We do have one specific hack to prevent conversion of (e.g.) “(a : Int, b : Int) -> Void” to “(b : Int, a : Int) -> Void”, but this only triggers in specific cases. There are other more complex cases as well, e.g. when using generics "T<(a : Int)->Int>” cannot be considered compatible with "T<(b : Int)->Int>”.

These problems are what initially motivated SE-0111. However, given the feedback, the core team went back to the drawing board to determine whether: a) SE-0111 by itself is the right long term answer, b) whether there were alternate models that could solve the same problems in a different way, or c) whether SE-0111 was the right first step to "ultimate glory" in the field of closure parameter labels. After a long discussion, and many alternatives considered, the core team believes in c), that SE-0111 (with a minor modification) is the right step for Swift 3, because it paves the way for the right model over the long term.

----8<----

The specific revision requested by the core team to SE-0111 is that all “cosmetic” labels should be required to include an API name of _. For example, this would not be allowed:

   var op : (lhs : Int, rhs : Int) -> Int

instead, it should be spelled as:

   var op : (_ lhs : Int, _ rhs : Int) -> Int

With this change, we believe that we have paved the way for a purely additive proposal (and thus, post-Swift 3) that will restore the expressive capability of closures with parameter labels.

----8<----

Here is a sketch of how that would work, in two steps:

First, we extend declaration names for variables, properties, and parameters to allow *parameter names* as part of their declaration name. For example:

   var op(lhs:,rhs:) : (Int, Int) -> Int // variable or property.
   x = op(lhs: 1, rhs: 2) // use of the variable or property.

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op(lhs:,rhs:) : (Int, Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // use of the parameter
   }
   foo(opToUse: +) // call of the function

This will restore the ability to express the idea of a closure parameter that carries labels as part of its declaration, without requiring parameter labels to be part of the type system (allowing, e.g. the operator + to be passed into something that requires parameter labels).

During the review, Michael Ilseman suggested using SE-0021 for declaration names.

<http://thread.gmane.org/gmane.comp.lang.swift.evolution/22488/focus=22580>

Your example "op(lhs:,rhs:)" would be "op(lhs:rhs:)" instead (i.e. without the comma).

-- Ben

···

On 14 Jul 2016, at 05:47, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

Second, extend the rules for function types to allow parameter API labels *if and only if* they are used as the type of a declaration that allows parameter labels, and interpret them as a sugar form for providing those labels on the underlying declaration. This means that the example above could be spelled as:

   var op : (lhs: Int, rhs: Int) -> Int // Nice declaration syntax
   x = op(lhs: 1, rhs: 2) // Same as above

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op : (lhs: Int, rhs: Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // Same as above.
   }
   foo(opToUse: +) // Same as above.

These two steps will provide the simple and expressive design approach that we have now, without all of the problems that representing parameter labels in the type system introduces. The core team believes that the temporary regression in expressiveness is an acceptable loss for Swift 3, particularly given that this will have no impact on Cocoa or the standard library. In the case of Cocoa, recall that C and Objective-C don’t have parameter labels on their corresponding concepts (Blocks and C function pointers), and the higher order functions in the standard library should not require parameter labels either.

-Chris & the Core Team


(Vladimir) #5

Just +100. One more wise decision from the core team. Thank you for all of your work.

···

On 14.07.2016 7:47, Chris Lattner via swift-evolution wrote:

Proposal:
https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

Shortly after SE-0111 was accepted last week, several people newly noticed
the proposal and started a discussion about how it appears to be a
regression for closure parameters (e.g. callbacks) that could formerly
carry labels, but are now not allowed to. These folks observed that it
would be more expressive (and consistent with the rest of Swift) to allow
parameter labels in function types, because the invocation site of a
closure “should" be required to provide those labels. The core team has
been following the discussion, agrees that this is a concern, and wants to
update the community with a path forward.

The reality of the situation is that the current implementation of
parameter labels in function types is inherently broken. Specifically, as
one example, there is an implicit conversion from "(a: Int) -> Int” to
“(Int) -> Int”. However, there is also an implicit conversion from "(Int)
-> Int” to “(b : Int) -> Int”. This means that the compiler currently
allows converting from “(a: Int) -> Int” to “(b: Int) -> Int”, which
doesn’t make sense, introduces surprising behavior, introduces complexity
into the compiler implementation, and is generally a problem. We do have
one specific hack to prevent conversion of (e.g.) “(a : Int, b : Int) ->
Void” to “(b : Int, a : Int) -> Void”, but this only triggers in specific
cases. There are other more complex cases as well, e.g. when using
generics "T<(a : Int)->Int>” cannot be considered compatible with "T<(b :
Int)->Int>”.

These problems are what initially motivated SE-0111. However, given the
feedback, the core team went back to the drawing board to determine
whether: a) SE-0111 by itself is the right long term answer, b) whether
there were alternate models that could solve the same problems in a
different way, or c) whether SE-0111 was the right first step to "ultimate
glory" in the field of closure parameter labels. After a long discussion,
and many alternatives considered, the core team believes in c), that
SE-0111 (with a minor modification) is the right step for Swift 3, because
it paves the way for the right model over the long term.

----8<----

The specific revision requested by the core team to SE-0111 is that all
“cosmetic” labels should be required to include an API name of _. For
example, this would not be allowed:

   var op : (lhs : Int, rhs : Int) -> Int

instead, it should be spelled as:

   var op : (_ lhs : Int, _ rhs : Int) -> Int

With this change, we believe that we have paved the way for a purely
additive proposal (and thus, post-Swift 3) that will restore the expressive
capability of closures with parameter labels.

----8<----

Here is a sketch of how that would work, in two steps:

First, we extend declaration names for variables, properties, and
parameters to allow *parameter names* as part of their declaration name.
For example:

   var op(lhs:,rhs:) : (Int, Int) -> Int // variable or property.
   x = op(lhs: 1, rhs: 2) // use of the variable or property.

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op(lhs:,rhs:) : (Int, Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // use of the parameter
   }
   foo(opToUse: +) // call of the function

This will restore the ability to express the idea of a closure parameter
that carries labels as part of its declaration, without requiring parameter
labels to be part of the type system (allowing, e.g. the operator + to be
passed into something that requires parameter labels).

Second, extend the rules for function types to allow parameter API labels
*if and only if* they are used as the type of a declaration that allows
parameter labels, and interpret them as a sugar form for providing those
labels on the underlying declaration. This means that the example above
could be spelled as:

   var op : (lhs: Int, rhs: Int) -> Int // Nice declaration syntax
   x = op(lhs: 1, rhs: 2) // Same as above

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op : (lhs: Int, rhs: Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // Same as above.
   }
   foo(opToUse: +) // Same as above.

These two steps will provide the simple and expressive design approach that
we have now, without all of the problems that representing parameter labels
in the type system introduces. The core team believes that the temporary
regression in expressiveness is an acceptable loss for Swift 3,
particularly given that this will have no impact on Cocoa or the standard
library. In the case of Cocoa, recall that C and Objective-C don’t have
parameter labels on their corresponding concepts (Blocks and C function
pointers), and the higher order functions in the standard library should
not require parameter labels either.

-Chris & the Core Team

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


(Diego Sánchez) #6

This is great news! Thank you!!

···

On Thursday, 14 July 2016, Chris Lattner via swift-evolution < swift-evolution@swift.org> wrote:

Proposal:
https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

Shortly after SE-0111 was accepted last week, several people newly noticed
the proposal and started a discussion about how it appears to be a
regression for closure parameters (e.g. callbacks) that could formerly
carry labels, but are now not allowed to. These folks observed that it
would be more expressive (and consistent with the rest of Swift) to allow
parameter labels in function types, because the invocation site of a
closure “should" be required to provide those labels. The core team has
been following the discussion, agrees that this is a concern, and wants to
update the community with a path forward.

The reality of the situation is that the current implementation of
parameter labels in function types is inherently broken. Specifically, as
one example, there is an implicit conversion from "(a: Int) -> Int” to “(Int)
-> Int”. However, there is also an implicit conversion from "(Int) -> Int”
to “(b : Int) -> Int”. This means that the compiler currently allows
converting from “(a: Int) -> Int” to “(b: Int) -> Int”, which doesn’t
make sense, introduces surprising behavior, introduces complexity into the
compiler implementation, and is generally a problem. We do have one
specific hack to prevent conversion of (e.g.) “(a : Int, b : Int) -> Void”
to “(b : Int, a : Int) -> Void”, but this only triggers in specific
cases. There are other more complex cases as well, e.g. when using
generics "T<(a : Int)->Int>” cannot be considered compatible with "T<(b :
Int)->Int>”.

These problems are what initially motivated SE-0111. However, given the
feedback, the core team went back to the drawing board to determine
whether: a) SE-0111 by itself is the right long term answer, b) whether
there were alternate models that could solve the same problems in a
different way, or c) whether SE-0111 was the right first step to "ultimate
glory" in the field of closure parameter labels. After a long discussion,
and many alternatives considered, the core team believes in c), that
SE-0111 (with a minor modification) is the right step for Swift 3, because
it paves the way for the right model over the long term.

----8<----

The specific revision requested by the core team to SE-0111 is that all
“cosmetic” labels should be required to include an API name of _. For
example, this would not be allowed:

   var op : (lhs : Int, rhs : Int) -> Int

instead, it should be spelled as:

   var op : (_ lhs : Int, _ rhs : Int) -> Int

With this change, we believe that we have paved the way for a purely
additive proposal (and thus, post-Swift 3) that will restore the expressive
capability of closures with parameter labels.

----8<----

Here is a sketch of how that would work, in two steps:

First, we extend declaration names for variables, properties, and
parameters to allow *parameter names* as part of their declaration name.
For example:

   var op(lhs:,rhs:) : (Int, Int) -> Int // variable or property.
   x = op(lhs: 1, rhs: 2) // use of the variable or property.

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op(lhs:,rhs:) : (Int, Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // use of the parameter
   }
   foo(opToUse: +) // call of the function

This will restore the ability to express the idea of a closure parameter
that carries labels as part of its declaration, without requiring parameter
labels to be part of the type system (allowing, e.g. the operator + to be
passed into something that requires parameter labels).

Second, extend the rules for function types to allow parameter API labels
*if and only if* they are used as the type of a declaration that allows
parameter labels, and interpret them as a sugar form for providing those
labels on the underlying declaration. This means that the example above
could be spelled as:

   var op : (lhs: Int, rhs: Int) -> Int // Nice declaration syntax
   x = op(lhs: 1, rhs: 2) // Same as above

   // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
   func foo(opToUse op : (lhs: Int, rhs: Int) -> Int) {
     x = op(lhs: 1, rhs: 2) // Same as above.
   }
   foo(opToUse: +) // Same as above.

These two steps will provide the simple and expressive design approach
that we have now, without all of the problems that representing parameter
labels in the type system introduces. The core team believes that the
temporary regression in expressiveness is an acceptable loss for Swift 3,
particularly given that this will have no impact on Cocoa or the standard
library. In the case of Cocoa, recall that C and Objective-C don’t have
parameter labels on their corresponding concepts (Blocks and C function
pointers), and the higher order functions in the standard library should
not require parameter labels either.

-Chris & the Core Team


(Chris Lattner) #7

Yes, we are sadly really almost out of time for Swift 3 and need to remain as hyper-focused as possible. There is always another release.

-Chris

···

On Jul 14, 2016, at 1:20 AM, Taras Zakharko <taras.zakharko@uzh.ch> wrote:

Great!

This cleanly separates between the type and the name/signature! Simple and consistent. Thank you!

A clarification question: do i understand correctly that steps 2 and 3 will not be included in Swift 3 due time constraints?


(Erica Sadun) #8

I was under the impression that Swift 2.3 was going to go gold in September for App Store submissions and Swift 3 in December. Is my timeline wrong?

-- E

···

On Jul 14, 2016, at 10:01 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 14, 2016, at 1:20 AM, Taras Zakharko <taras.zakharko@uzh.ch> wrote:

Great!

This cleanly separates between the type and the name/signature! Simple and consistent. Thank you!

A clarification question: do i understand correctly that steps 2 and 3 will not be included in Swift 3 due time constraints?

Yes, we are sadly really almost out of time for Swift 3 and need to remain as hyper-focused as possible. There is always another release.

-Chris


(Chris Lattner) #9

Ok, sure. I just trying to outline what the proposal would look like,

-Chris

···

On Jul 14, 2016, at 9:33 AM, Ben Rimmington <me@benrimmington.com> wrote:

This will restore the ability to express the idea of a closure parameter that carries labels as part of its declaration, without requiring parameter labels to be part of the type system (allowing, e.g. the operator + to be passed into something that requires parameter labels).

During the review, Michael Ilseman suggested using SE-0021 for declaration names.

<http://thread.gmane.org/gmane.comp.lang.swift.evolution/22488/focus=22580>

Your example "op(lhs:,rhs:)" would be "op(lhs:rhs:)" instead (i.e. without the comma).


(Thorsten Seitz) #10

Just +100. One more wise decision from the core team. Thank you for all of your work.

Indeed! Thank you!

-Thorsten

···

Am 14.07.2016 um 16:46 schrieb Vladimir.S via swift-evolution <swift-evolution@swift.org>:

On 14.07.2016 7:47, Chris Lattner via swift-evolution wrote:
Proposal:
https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

Shortly after SE-0111 was accepted last week, several people newly noticed
the proposal and started a discussion about how it appears to be a
regression for closure parameters (e.g. callbacks) that could formerly
carry labels, but are now not allowed to. These folks observed that it
would be more expressive (and consistent with the rest of Swift) to allow
parameter labels in function types, because the invocation site of a
closure “should" be required to provide those labels. The core team has
been following the discussion, agrees that this is a concern, and wants to
update the community with a path forward.

The reality of the situation is that the current implementation of
parameter labels in function types is inherently broken. Specifically, as
one example, there is an implicit conversion from "(a: Int) -> Int” to
“(Int) -> Int”. However, there is also an implicit conversion from "(Int)
-> Int” to “(b : Int) -> Int”. This means that the compiler currently
allows converting from “(a: Int) -> Int” to “(b: Int) -> Int”, which
doesn’t make sense, introduces surprising behavior, introduces complexity
into the compiler implementation, and is generally a problem. We do have
one specific hack to prevent conversion of (e.g.) “(a : Int, b : Int) ->
Void” to “(b : Int, a : Int) -> Void”, but this only triggers in specific
cases. There are other more complex cases as well, e.g. when using
generics "T<(a : Int)->Int>” cannot be considered compatible with "T<(b :
Int)->Int>”.

These problems are what initially motivated SE-0111. However, given the
feedback, the core team went back to the drawing board to determine
whether: a) SE-0111 by itself is the right long term answer, b) whether
there were alternate models that could solve the same problems in a
different way, or c) whether SE-0111 was the right first step to "ultimate
glory" in the field of closure parameter labels. After a long discussion,
and many alternatives considered, the core team believes in c), that
SE-0111 (with a minor modification) is the right step for Swift 3, because
it paves the way for the right model over the long term.

----8<----

The specific revision requested by the core team to SE-0111 is that all
“cosmetic” labels should be required to include an API name of _. For
example, this would not be allowed:

  var op : (lhs : Int, rhs : Int) -> Int

instead, it should be spelled as:

  var op : (_ lhs : Int, _ rhs : Int) -> Int

With this change, we believe that we have paved the way for a purely
additive proposal (and thus, post-Swift 3) that will restore the expressive
capability of closures with parameter labels.

----8<----

Here is a sketch of how that would work, in two steps:

First, we extend declaration names for variables, properties, and
parameters to allow *parameter names* as part of their declaration name.
For example:

  var op(lhs:,rhs:) : (Int, Int) -> Int // variable or property.
  x = op(lhs: 1, rhs: 2) // use of the variable or property.

  // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
  func foo(opToUse op(lhs:,rhs:) : (Int, Int) -> Int) {
    x = op(lhs: 1, rhs: 2) // use of the parameter
  }
  foo(opToUse: +) // call of the function

This will restore the ability to express the idea of a closure parameter
that carries labels as part of its declaration, without requiring parameter
labels to be part of the type system (allowing, e.g. the operator + to be
passed into something that requires parameter labels).

Second, extend the rules for function types to allow parameter API labels
*if and only if* they are used as the type of a declaration that allows
parameter labels, and interpret them as a sugar form for providing those
labels on the underlying declaration. This means that the example above
could be spelled as:

  var op : (lhs: Int, rhs: Int) -> Int // Nice declaration syntax
  x = op(lhs: 1, rhs: 2) // Same as above

  // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
  func foo(opToUse op : (lhs: Int, rhs: Int) -> Int) {
    x = op(lhs: 1, rhs: 2) // Same as above.
  }
  foo(opToUse: +) // Same as above.

These two steps will provide the simple and expressive design approach that
we have now, without all of the problems that representing parameter labels
in the type system introduces. The core team believes that the temporary
regression in expressiveness is an acceptable loss for Swift 3,
particularly given that this will have no impact on Cocoa or the standard
library. In the case of Cocoa, recall that C and Objective-C don’t have
parameter labels on their corresponding concepts (Blocks and C function
pointers), and the higher order functions in the standard library should
not require parameter labels either.

-Chris & the Core Team

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

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


(Chris Lattner) #11

Both Swift 2.3 and Swift 3 will GM along with Xcode 8 and iOS 10, whenever that ends up being. Did I say something to contradict that? I don’t know what Swift 2.3 has to do with this thread.

-Chris

···

On Jul 14, 2016, at 9:27 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Jul 14, 2016, at 10:01 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 14, 2016, at 1:20 AM, Taras Zakharko <taras.zakharko@uzh.ch> wrote:

Great!

This cleanly separates between the type and the name/signature! Simple and consistent. Thank you!

A clarification question: do i understand correctly that steps 2 and 3 will not be included in Swift 3 due time constraints?

Yes, we are sadly really almost out of time for Swift 3 and need to remain as hyper-focused as possible. There is always another release.

-Chris

I was under the impression that Swift 2.3 was going to go gold in September for App Store submissions and Swift 3 in December. Is my timeline wrong?