[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