[Core team] Addressing the SE-0110 usability regression in Swift 4


(Douglas Gregor) #1

Hello Swift community,

Swift 3’s SE-0110 <https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md> eliminated the equivalence between function types that accept a single type and function types that take multiple arguments. However, for various implementation reasons <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170612/037560.html>, the implementation of SE-0110 (as well as the elimination of tuple “splat” behavior in SE-0029 <https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md>) was not fully completed.

Swift 4 implemented more of SE-0110, which caused a fairly serious usability regression, particularly with closures. Here are a few simple examples involving closures that worked in Swift 3 but do not work in Swift 4:

// #1: Works in Swift 3, error in Swift 4
myDictionary.forEach {
  print("\($0) -> \($1)")
}

// #2: Works in Swift 3, error in Swift 4
myDictionary.forEach { key, value in
  print("\(key) -> \(value)")
}

// #3: Works in Swift 3, error in Swift 4
myDictionary.forEach { (key, value) in
  print("\(key) -> \(value)")
}

Similar issues occur with passing multi-argument functions where a tuple argument is expected:

// #4: Works in Swift 3, error in Swift 4
_ = zip(array1, array2).map(+)

In all of these cases, it is possible to write a closure that achieves the desired effect, but the result is more verbose and less intuitive:

// Works in both Swift 3 and Swift 4
myDictionary.forEach { element in
  let (key, value) = element
  print("\(key) -> \(value)")
}

The Swift core team feels that these usability regressions are unacceptable for Swift 4. There are a number of promising solutions that would provide a better model for closures and address the usability regression, but fully designing and implementing those are out of scope for Swift 4. Therefore, we will “back out” the SE-0110 change regarding function arguments from Swift 4.

Specifically, when passing an argument value of function type (including closures) to a parameter of function type, a multi-parameter argument function can be passed to a parameter whose function type accepts a single tuple (whose tuple elements match the parameter types of the argument function). Practically speaking, all of the examples #1-#4 will be accepted in both Swift 3 and Swift 4.

We will revisit the design in this area post-Swift 4.

  - Doug


#2

Yay!


(Víctor Pimentel) #3

Thank you :slight_smile:

···

On Tue, 20 Jun 2017 at 01:41, Douglas Gregor via swift-evolution < swift-evolution@swift.org> wrote:

Hello Swift community,

Swift 3’s SE-0110
<https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md> eliminated
the equivalence between function types that accept a single type and
function types that take multiple arguments. However, for various implementation
reasons
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170612/037560.html>,
the implementation of SE-0110 (as well as the elimination of tuple “splat”
behavior in SE-0029
<https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md>)
was not fully completed.

Swift 4 implemented more of SE-0110, which caused a fairly serious
usability regression, particularly with closures. Here are a few simple
examples involving closures that worked in Swift 3 but do not work in Swift
4:

// #1: Works in Swift 3, error in Swift 4
myDictionary.forEach {
  print("\($0) -> \($1)")
}

// #2: Works in Swift 3, error in Swift 4
myDictionary.forEach { key, value in
  print("\(key) -> \(value)")
}

// #3: Works in Swift 3, error in Swift 4
myDictionary.forEach { (key, value) in
  print("\(key) -> \(value)")
}

Similar issues occur with passing multi-argument functions where a tuple
argument is expected:

// #4: Works in Swift 3, error in Swift 4
_ = zip(array1, array2).map(+)

In all of these cases, it is possible to write a closure that achieves the
desired effect, but the result is more verbose and less intuitive:

// Works in both Swift 3 and Swift 4
myDictionary.forEach { element in
  let (key, value) = element
  print("\(key) -> \(value)")
}

The Swift core team feels that these usability regressions are
unacceptable for Swift 4. There are a number of promising solutions that
would provide a better model for closures and address the usability
regression, but fully designing and implementing those are out of scope for
Swift 4. Therefore, we will “back out” the SE-0110 change regarding
function arguments from Swift 4.

Specifically, when passing an argument value of function type (including
closures) to a parameter of function type, a multi-parameter argument
function can be passed to a parameter whose function type accepts a single
tuple (whose tuple elements match the parameter types of the argument
function). Practically speaking, all of the examples #1-#4 will be accepted
in both Swift 3 and Swift 4.

We will revisit the design in this area post-Swift 4.

- Doug

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

--
Víctor Pimentel
--

D I G I T A L T E L C O E X P E R I E N C E

*[image: Imágenes integradas 5]*

*Víctor Pimentel Rodríguez · *Principal iOS Engineer
vpimentel@tuenti.com

+34 914 294 039 <javascript:void(0);> — +34 687 840 886
<javascript:void(0);>
C/ Gran Vía, nº 28, 6ª planta — 28013 Madrid
Tuenti Technologies, S.L.

www.tu.com
www.tuenti.com


#4

A plain, simple, but very deep THANK YOU!

Gwendal Roué

···

Le 20 juin 2017 à 01:40, Douglas Gregor via swift-evolution <swift-evolution@swift.org> a écrit :

Hello Swift community,

Swift 3’s SE-0110 <https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md> eliminated the equivalence between function types that accept a single type and function types that take multiple arguments. However, for various implementation reasons <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170612/037560.html>, the implementation of SE-0110 (as well as the elimination of tuple “splat” behavior in SE-0029 <https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md>) was not fully completed.

Swift 4 implemented more of SE-0110, which caused a fairly serious usability regression, particularly with closures. Here are a few simple examples involving closures that worked in Swift 3 but do not work in Swift 4:

// #1: Works in Swift 3, error in Swift 4
myDictionary.forEach {
  print("\($0) -> \($1)")
}

// #2: Works in Swift 3, error in Swift 4
myDictionary.forEach { key, value in
  print("\(key) -> \(value)")
}

// #3: Works in Swift 3, error in Swift 4
myDictionary.forEach { (key, value) in
  print("\(key) -> \(value)")
}

Similar issues occur with passing multi-argument functions where a tuple argument is expected:

// #4: Works in Swift 3, error in Swift 4
_ = zip(array1, array2).map(+)

In all of these cases, it is possible to write a closure that achieves the desired effect, but the result is more verbose and less intuitive:

// Works in both Swift 3 and Swift 4
myDictionary.forEach { element in
  let (key, value) = element
  print("\(key) -> \(value)")
}

The Swift core team feels that these usability regressions are unacceptable for Swift 4. There are a number of promising solutions that would provide a better model for closures and address the usability regression, but fully designing and implementing those are out of scope for Swift 4. Therefore, we will “back out” the SE-0110 change regarding function arguments from Swift 4.

Specifically, when passing an argument value of function type (including closures) to a parameter of function type, a multi-parameter argument function can be passed to a parameter whose function type accepts a single tuple (whose tuple elements match the parameter types of the argument function). Practically speaking, all of the examples #1-#4 will be accepted in both Swift 3 and Swift 4.

We will revisit the design in this area post-Swift 4.

  - Doug

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