[swift-evolution] [Proposal] Disallow implicit conversion between function/closure with a list of parameters and with tuple parameter. Remove function type inconsistency.

Saagar Jha saagarjha28 at gmail.com
Sun Jun 26 23:13:48 CDT 2016


+1. I had this same problem when using map with enumerated-both $1 and
$0.offset worked. I can see how this can be confusing to beginners.


On Sat, Jun 25, 2016 at 8:36 AM Vladimir.S via swift-evolution <
swift-evolution at swift.org> 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
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-- 
-Saagar Jha
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160627/a77358ab/attachment.html>


More information about the swift-evolution mailing list