+1 to this; I seem to keep running into cases of this, and it crops up especially when Swift is having difficulty inferring a type, which can be tricky to debug as it is, so I think it's better to just be consistent and explicit, with double brackets for all tuple type closures as proposed.
> On 25 Jun 2016, at 16:35, Vladimir.S via swift-evolution > <[email protected]> wrote: > > 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 _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
