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

Thorsten Seitz tseitz42 at icloud.com
Sat Jul 16 14:39:42 CDT 2016

> Am 14.07.2016 um 16:46 schrieb Vladimir.S via swift-evolution <swift-evolution at swift.org>:
> Just +100. One more wise decision from the core team. Thank you for all of your work.

Indeed! Thank you!


>> 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 at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

More information about the swift-evolution mailing list