I believe this should be done for Swift 3.0 release as this is a *source breaking change* and IMO it is very important to remove the inconsistency mentioned below.

We removed tuple splatting on caller side and IMO we must complete this job to delete the implicit connection between tuple and list of parameters in closures/functions.


Currently we have these "features" :
====================================

1. Single tuple as parameter is allowed when list of parameters are required:

let ft1 : (Int,Int) -> Void = { x in print(x.0, x.1)}

(but this causes crash:
let ft2 : (Int,Int) -> Void = { x in print(x) }
)

Opinion: this should not be allowed. Parameter list is required.
`(Int,Int) -> Void` and `((Int,Int)) -> Void` are two different types.


2. Parameter list in closure is allowed when single tuple parameter is required:

typealias IntInt = (Int,Int)
typealias IntIntToVoid = (IntInt) -> Void

let tuple : IntInt = (1,2)

func foo(block: IntIntToVoid) { block(tuple) }

foo { x, y in print(x,y)}
foo { (x, y) in print(x, y)}

Opinion: this should not be allowed. Tuple parameter is required.
`((Int,Int)) -> Void` and `(Int,Int) -> Void` are two different types.
Swift should require this syntax to assign tuple parameter's sub-values to variables in closure: `{ ((x, y)) in ..}`


3. Inconsistent (and just wrong) function type when a list of parameters required(not tuple) :

typealias t1 = (Int, Int) -> Int // clearly here are list of parameters
typealias t2 = ((Int, Int)) -> Int // clearly here is a tuple parameter

print(t1.self) // Prints ((Int, Int)) -> Int  why?
print(t2.self) // Prints ((Int, Int)) -> Int
print(t1.self == t2.self) // true

Opinion: `(Int,Int) -> Void` and `((Int,Int)) -> Void` should be two different separate types that can not be implicitly converted to each other. Swift's typesystem should separate these types.


4. If the type is the same, why behavior differs :

let add_list:  (Int, Int) -> Int = (+)
let add_tuple: ((Int, Int)) -> Int = (+)

print(add_list.dynamicType == add_tuple.dynamicType) // true

print( add_list(1,2) )
//print( add_list((1,2)) ) // missing argument for parameter #2 in call

//print( add_tuple(1,2) ) // extra argument in call
print( add_tuple((1,2)) )


Proposal:
===============

1. Separate function types with parameter list and a tuple parameter. They should be two separate types.

2. Require this syntax to assign tuple parameter's sub-values to variables in func/closure: `{ ((x, y)) in ..}`, otherwise (i.e. if `{ (x, y) in ..`) treat function/closure as having list of parameters.

3. Disallow implicit conversion between function/closure with a list of parameters and function/closure where single tuple is required. This will stop confusion and make the language consistent how it deal with tuples and list of parameters in func/closure.

4. It seems like we should keep the ability to explicitly convert one to another as some(many?) code can depend on this current behavior and so we need a way to convert old code to new.
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to