[swift-evolution] Proposal: Always flatten the single element tuple

Vladimir.S svabox at gmail.com
Wed Jun 7 07:42:54 CDT 2017


On 07.06.2017 14:18, Gwendal Roué via swift-evolution wrote:
> Xiaodi, Adrian, you are actively pushing so that something that was allowed, well 
> compiled (no runtime issue), and covered actual uses cases, becomes forbidden. 
> Without any developer advantage that would somehow balance the change.
> 
> That's called a regression.
> 
> And what's the rationale, already? A sense of compiler aesthetics? Since when a sense 
> of compiler aesthetics is more valuable than a sense of code aesthetics? Aren't both 
> supposed to walk together as a pair?

Gwendal, again, you are proposing to revert not just SE-0110 and SE-0066 but mainly 
SE-0029 "Remove implicit tuple splat behavior from function applications"
(https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md)

Here is rationale for acceptance of this proposal:
(Joe Groff jgroff at apple.com)
(Wed Feb 10 11:51:16 CST 2016)

The review of "SE-0029 Remove implicit tuple splat behavior from function 
applications" ran from February 5...February 9, 2016. The proposal has been accepted 
for Swift 3. We acknowledge that we're removing a useful feature without providing an 
equally expressive drop-in replacement. However, maintaining this behavior in the 
type checker is a severe source of implementation complexity, and actively interferes 
with our plans to solidify the type system. We feel that removing the existing 
behavior is a necessary step toward stabilizing the language and toward building a 
well-designed alternative feature for explicit argument forwarding in the future.

(https://lists.swift.org/pipermail/swift-evolution-announce/2016-February/000033.html)

We can discuss what sugar we can have to have tuple destructuring in closure and 
probably some sugar to allow free function of list of arguments when function of one 
tuple is required. But I don't see how we can revisit(and I believe we shouldn't) a 
number of actively discussed(!) and accepted proposals and dramatically change 
direction of Swift evolution even because of "lacks in terms of user ergonomics" for 
some period.


Btw, please also note that this will not be possible in Swift 4:
func f() {}
let c : ()->() = { v in print(v) }
c() // prints ()
f(print("fdsdf")) // executes print and then f()
, as function declared without parameters now can't accept even Void argument, 
function parenthesis is not empty tuple, as was allowed in Swift 3. Now you'll have 
these errors:

error: contextual closure type '() -> ()' expects 0 arguments, but 1 was used in 
closure body
let c : ()->() = { v in print(v) }
                    ^
error: argument passed to call that takes no arguments
f(print("fdsdf"))
   ^~~~~~~~~~~~~~

Probably this "feature" also was used in Swift 3 code, do we need to revisit it also? 
(I believe no)

> 
> Gwendal
> 
>> Le 7 juin 2017 à 12:54, Xiaodi Wu <xiaodi.wu at gmail.com 
>> <mailto:xiaodi.wu at gmail.com>> a écrit :
>>
>> IMO, if tuples and argument lists are to be distinguished in any way, it is 
>> imperative that f3(+) and f4(+), and some of your other examples, _not_ work.
>>
>> After all, if a tuple is not an argument list, it should possible to have a 
>> function of type ((Int, Int)) -> Int and a function of type (Int, Int) -> Int share 
>> the same name (IIUC, it’s a known bug that this does not currently work). Quite 
>> simply, there’s a type mismatch if you pass sum1 to f3–what happens if there’s a 
>> distinct, overloaded sum1 that takes a single tuple?
>>
>> Chris’s suggestion restores a syntactic convenience without touching the type 
>> system. What you are arguing for is essentially making ((Int, Int)) -> Int and 
>> (Int, Int) -> Int synonymous again, either in some or in all contexts.
>>
>>
>> On Wed, Jun 7, 2017 at 05:41 Gwendal Roué via swift-evolution 
>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>
>>>     Le 7 juin 2017 à 12:33, Gwendal Roué <gwendal.roue at gmail.com
>>>     <mailto:gwendal.roue at gmail.com>> a écrit :
>>>
>>>
>>>>     Le 7 juin 2017 à 12:03, Adrian Zubarev via swift-evolution
>>>>     <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> a écrit :
>>>>
>>>>     Well please no:
>>>>
>>>>     
|let fn2: ((Int, Int)) -> Void = { lhs, rhs in }|
>>>>
>>>>     Instead use destructuring sugar pitched by Chris Lattner on the other thread:
>>>>
>>>>     |let fn2: ((Int, Int)) -> Void = { ((lhs, rhs)) in }|
>>>>
>>>
>>>     Despite Chris Lattern being a semi-god, his double-parenthesis suggestion
>>>     cruelly lacks in terms of user ergonomics. The compiler should be able to deal
>>>     with the following code snippet, just like Swift 3 does:
>>>
>>>     // two arguments
>>>     funcf1(_closure: (Int, Int) -> Int) { closure(1, 2) }
>>>     [...]
>>
>>     Here is the full extent of the remarquable Swift 3 ergonomics. This full
>>     snippet compiles in Swift 3:
>>
>>     funcsum1(_lhs: Int, _rhs: Int) -> Int{ returnlhs + rhs }
>>     funcsum2(lhs: Int, rhs: Int) -> Int{ returnlhs + rhs }
>>     funcsum3(tuple: (Int, Int)) -> Int{ returntuple.0 + tuple.1 }
>>     funcsum4(tuple: (lhs: Int, rhs: Int)) -> Int{ returntuple.lhs + tuple.rhs }
>>
>>     // two arguments
>>     funcf1(_closure: (Int, Int) -> Int) { closure(1, 2) }
>>     f1{ lhs, rhs inlhs + rhs }
>>     f1{ (lhs, rhs) inlhs + rhs }
>>     f1{ tuple intuple.0 + tuple.1 }
>>     f1{ (tuple) intuple.0 + tuple.1 }
>>     f1(+)
>>         f1(sum1)
>>         f1(sum2)
>>         f1(sum3)
>>         f1(sum4)
>>
>>     // two arguments, with documentation names: identical
>>     funcf2(_closure: (_a: Int, _b: Int) -> Int) { closure(1, 2) }
>>     f2{ lhs, rhs inlhs + rhs }
>>     f2{ (lhs, rhs) inlhs + rhs }
>>     f2{ tuple intuple.0 + tuple.1 }
>>     f2{ (tuple) intuple.0 + tuple.1 }
>>     f2(+)
>>         f2(sum1)
>>         f2(sum2)
>>         f2(sum3)
>>         f2(sum4)
>>
>>     // one tuple argument
>>     funcf3(_closure: ((Int, Int)) -> Int) { closure((1, 2)) }
>>     f3{ lhs, rhs inlhs + rhs }
>>     f3{ (lhs, rhs) inlhs + rhs }
>>     f3{ tuple intuple.0 + tuple.1 }
>>     f3{ (tuple) intuple.0 + tuple.1 }
>>     f3(+)
>>         f3(sum1)
>>         f3(sum2)
>>         f3(sum3)
>>         f3(sum4)
>>
>>     // one keyed tuple argument
>>     funcf4(_closure: ((a: Int, b: Int)) -> Int) { closure((a: 1, b: 2)) }
>>     f4{ lhs, rhs inlhs + rhs }
>>     f4{ (lhs, rhs) inlhs + rhs }
>>     f4{ tuple intuple.a + tuple.b }
>>     f4{ (tuple) intuple.a + tuple.b }
>>     f4(+)
>>         f4(sum1)
>>         f4(sum2)
>>         f4(sum3)
>>         f4(sum4)
>>
>>     Gwendal
>>
>>     _______________________________________________
>>     swift-evolution mailing list
>>     swift-evolution at swift.org <mailto: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