[swift-evolution] Revisiting SE-0110

Vladimir.S svabox at gmail.com
Mon May 29 14:18:29 CDT 2017


On 29.05.2017 21:08, Nevin Brackett-Rozinsky wrote:
> Vladimir, using your function definitions I would like to have:
> 
> // Two parameters:
> barParams{ t in }       // invalid, too few parameters
> barParams{ (t) in }     // invalid, too few parameters
> barParams{ x, y in }    // valid, two parameters
> barParams{ (x, y) in }  // valid, two parameters with optional parentheses
> barParams{ ((x, y)) in }// invalid, too few parameters

OK, the same as I suggest.

> 
> // One parameter which is a 2-tuple:
> barTuple{ t in }        // valid, one tuple parameter
> barTuple{ (t) in }      // valid, one tuple parameter with optional parentheses
> barTuple{ x, y in }     // invalid, too many parameters

OK..

> barTuple{ (x, y) in }   // valid, destructuring one tuple
> barTuple{ ((x, y)) in } // valid, destructuring one tuple with optional parentheses

Here is the problem for me. According to SE-0066 closure declared as {(x,y) in} 
should be of type (Int,Int)->() and not ((Int,Int))->().
Why do you want to be able to pass wrong function/closure type into barTuple?

> For completeness: if a closure takes *any number* of parameters, it should be legal 
> to list one identifier per parameter, separated by commas, with optionally a pair of 
> parentheses surrounding that list. Furthermore, if *any* parameter is a tuple, it 
> should be possible to replace the identifier corresponding to that parameter with a 
> pair of parentheses containing a number of identifiers (separated by commas) equal to 
> the arity of the tuple. And this tuple-destructuring should work recursively, so if a 
> tuple contains a tuple [contains a tuple…] the inner tuples may optionally be 
> destructured as well.

Well.. Theoretically I don't see any problem with this in suggested "double pair of 
parentheses" syntax:

typealias MyTuple = (Int, (String, (Double, Bool)))

func doSomething(callback: ((Int, Int), MyTuple)->()) {}

doSomething {point, mytuple in }
doSomething {((x,y)), mytuple in }
doSomething {((x,y)), ((i, sdb)) in }
doSomething {point, ((i, ((s, ((d, b)))))) in }

//probably even just that flat syntax if all values are destructured
doSomething {((x, y)), ((i, s, d, b)) in }

doSomething {(t, myt) in } // here we see that there are 2 arguments, not tuples
doSomething {(((x,y)), myt) in }
doSomething {(((x,y)), ((i, tuple))) in }
doSomething {(point, ((i, ((s, ((d, b))))))) in }

the double parentheses in closure argument declaration clearly shows that this is a 
tuple deconstruction.

The question if we'll decide to allow such feature(extended ability for tuple 
deconstructing in closure arguments).

> 
> To be clear: each tuple being destructured must have a pair of parentheses containing 
> the identifiers it is being destructured into. It is only the very outermost 
> parentheses around the entire parameter list of the closure which should be optional.
> 

I see your position, but as I said, IMO single pair of parentheses is very ambiguous 
if it is a list of arguments or tuple deconstruction and we shouldn't disallow 
single pair of parentheses to surround a simple list of closure arguments in declaration.

> Nevin
> 
> 
> 
> On Mon, May 29, 2017 at 1:32 PM, Vladimir.S <svabox at gmail.com 
> <mailto:svabox at gmail.com>> wrote:
> 
>     On 29.05.2017 18:26, Nevin Brackett-Rozinsky via swift-evolution wrote:
> 
>         On Sun, May 28, 2017 at 7:04 PM, John McCall via swift-evolution
>         <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>         <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>> wrote:
> 
> 
>              We need to add back tuple destructuring in closure parameter lists
>         because this
>              is a serious usability regression.  If we're reluctant to just "do the right
>              thing" to handle the ambiguity of (a,b), we should at least allow it via
>              unambiguous syntax like ((a,b)).  I do think that we should just "do the
>         right
>              thing", however, with my biggest concern being whether there's any
>         reasonable way
>              to achieve that in 4.0.
> 
>              John.
> 
> 
>         I agree with John, the best thing for actually using Swift is to allow tuple
>         destructuring here, and the outermost parentheses (around the entire
>         parameter list of a closure) should continue to be optional. Requiring
>         double-parens would seem unnecessarily and arbitrarily…whatever the opposite
>         of “convenient” is.
> 
>         Nevin
> 
> 
>     If I understand correctly, correct me if I'm wrong, after *full* implementation
>     of SE-0066, the function with two parameters should have different type than
>     function with one tuple parameter:
> 
>     I.e.
>     typealias FuncParams = (Int, Int)->()
>     typealias FuncTuple = ((Int, Int))->()
> 
>     print(FuncParams.self) // should be (Int, Int)->()
>     print(FuncTuple.self) // should be ((Int, Int))->()
> 
>     So, if we have
> 
>     func barParams(_ f: FuncParams) {
>              f(1,2)
>     }
> 
>     func barTuple(_ f: FuncTuple) {
>              f((1,2))
>     }
> 
>     and
> 
>     func fooWithParams(_ x: Int,  _ y: Int) {  }
>     func fooWithTuple(_ tuple: (Int, Int)) {  }
> 
>     .. we should not be able to call
> 
>     barParams(fooWithTuple) // should be error: incompatible types
>     barTuple(fooWithParams) // should be error: incompatible types
> 
> 
>     If so, are you suggesting that this code should still be valid?
> 
>     barParams({tuple in}) // ?
>     barTuple({x,y in}) // ?
> 
> 
>     Will {x,y in} closure has ((Int, Int))->() type in this case?
>     And if {tuple in} should be of type (Int,Int)->() ?
> 
>     If I'm not missing something, the only reasonable solution here is follow the
>     SE-0066 rules for function types and allow special syntax ((x,y)) to deconstruct
>     tuple parts in closure argument list, and such closure will have type
>     ((Int,Int))->() as expected. So we'll have:
> 
>     barTuple({((x,y)) in ... })
> 
> 
> 
> 
> 
>         _______________________________________________
>         swift-evolution mailing list
>         swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>         https://lists.swift.org/mailman/listinfo/swift-evolution
>         <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> 


More information about the swift-evolution mailing list