I, for one, would be willing to accept Xiaodi's suggestion involving `let`–especially if (pipe dream follows) we could use the same syntax in functions/methods to destructure parameters.
On Thu, Jun 1, 2017 at 3:32 PM, Vladimir.S via swift-evolution < [email protected]> wrote: > On 01.06.2017 19:31, Tommaso Piazza wrote: > >> Dear all, >> >> I made a comparison of Swift's 4 lack of tuple unsplatting, here is how >> it stands in comparison with other languages >> >> https://gist.github.com/blender/53f9568617654c38a219dd4a8353d935 >> >> > Thank you! Very useful information. And also I really like the opinion of > @AliSoftware in comments for this article. > > I'd suggest to add this variant to Swift section in your article: > > let eighteenOrMore = ["Tom" : 33, "Rebecca" : 17, "Siri" : 5].filter { > (arg: (name: String, age: Int)) in arg.age >= 18 } > > (I believe it is better that 2 others Swift variants.) > > It seems for me that we need to allow some special syntax for *explicit* > tuple destructuring in closures to make all happy. > > FWIW These suggestions are my favorite: > > 1. Just allow type inference for tuple's destructured variables in this > position: > > .filter { (arg: (name, age)) in arg.age >= 18 } > > > 2. (1) + allow underscore for tuple argument name: > > .filter { (_: (name, age)) in age >= 18 } > > > 3. (2) + allow to omit parenthesis (probably only in case of just one > tuple argument) > > .filter { _: (name, age) in age >= 18 } > > > 4. Use pattern matching syntax: > > .filter { case let (name, age) in age >= 18 } > > (looks similar as allowed today: if case let (name, age) = x { print(name, > age) } ) > > > 5. Use two pairs of parenthesis : > > .filter { ((name, age)) in age >= 18 } > > Btw, about the 5th variant. If took what is allowed today: > .filter { (arg: (name: String, age: Int)) in arg.age >= 18 } > , and allow type inference for tuple part arguments, we'll have this: > .filter { (arg: (name, age)) in arg.age >= 18 } > , and if additionally allow skipping of tuple argument declaration we'll > have: > .filter { ((name, age)) in arg.age >= 18 } > I.e. two pairs for parenthesis for tuple destructuring, and such syntax is > similar to the type this closure should have : ((String, Int)) -> Bool > > > >> >> >> On Thursday, June 1, 2017 12:25 PM, Vladimir.S via swift-evolution < >> [email protected]> wrote: >> >> >> On 01.06.2017 0:42, John McCall wrote: >> >> On May 31, 2017, at 2:02 PM, Stephen Celis <[email protected] >> <mailto:[email protected]>> wrote: >> >>> On May 28, 2017, at 7:04 PM, John McCall via swift-evolution >> >>> <[email protected] <mailto:[email protected]>> >> wrote: >> >>> >> >>> Yes, I agree. 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. >> >> >> >> Closure parameter lists are unfortunately only half of the equation >> here. This >> >> change also regresses the usability of point-free expression. >> > >> > The consequences for point-free style were expected and cannot really >> be >> > eliminated without substantially weakening SE-0110. Closure >> convenience seems to >> > me to be a much more serious regression. >> >> John, do you also want to say "and without weakening SE-0066"? Because, >> if I >> understand correctly, in this case: >> >> func add(_ x: Int, _ y: Int) -> Int { >> return x + y >> } >> >> zip([1, 2, 3], [4, 5, 6]).map(add) >> >> .. we have a clear function type mismatch situation, when map() expects >> function of >> type ((Int, Int))->Int, but function of type (Int,Int)->Int is provided ? >> So probably >> the additional 'reason' of the 'problem' in this case is SE-0066, no? >> Or I don't understand the SE-0066 correctly.. >> Do we want to allow implicit conversions between function type >> ((Int,Int))->Int and >> (Int,Int)->Int? >> >> Quote from SE-0066: >> --- >> (Int, Int) -> Int // function from Int and Int to Int >> ((Int, Int)) -> Int // function from tuple (Int, Int) to Int >> --- >> >> During this discussion I see a wish of some group of developers to just >> return back >> tuple splatting for function/closure arguments, so they can freely send >> tuple to >> function/closure accepting a list of parameters(and probably vise-versa). >> Is it worth to follow SE-0066 and SE-0110 as is, i.e. disallow tuple >> deconstructing >> and then, as additive change improve the situation with tuple >> splatting/deconstructing later with separate big proposal? >> >> Btw, about the SE-0110 proposal. It was discussed, formally reviewed and >> accepted. I >> expect that its revision also should be formally >> proposed/reviewed/accepted to >> collect a wide range of opinions and thoughts, and attract the attention >> of >> developers in this list to the subject. >> >> >> Also, if we revisit SE-0110, will this code be allowed?: >> >> func foo(_ callback: ((Int,Int))->Void) {} >> let mycallback = {(x:Int, y:Int)->Void in } >> foo(mycallback) >> >> and >> >> func foo(_ callback: (Int,Int)->Void) {} >> let mycallback = {(x: (Int, Int))->Void in } >> foo(mycallback) >> >> If so, what will be result of this for both cases? : >> >> print(type(of:mycallback)) // (Int,Int)->Void or ((Int,Int))->Void >> >> If allowed, do we want to allow implicit conversion between types >> (Int,Int)->Void and >> ((Int,Int))->Void in both directions? (Hello tuple splatting?) >> >> >> > >> > John. >> > >> > >> >> >> >> func add(_ x: Int, _ y: Int) -> Int { return x + y } >> >> >> >> zip([1, 2, 3], [4, 5, 6]).map(add) >> >> >> >> // error: nested tuple parameter '(Int, Int)' of function >> '(((_.Element, >> >> _.Element)) throws -> _) throws -> [_]' does not support destructuring >> >> >> >> This may not be a common pattern in most projects, but we heavily use >> this style >> >> in the Kickstarter app in our functional and FRP code. Definitely not >> the most >> >> common coding pattern, but a very expressive one that we rely on. >> >> >> >> Our interim solution is a bunch of overloaded helpers, e.g.: >> >> >> >> func tupleUp<A, B, C>(_ f: (A, B) -> C) -> ((A, B)) -> C { return } >> >> >> >> zip([1, 2, 3], [4, 5, 6]).map(tupleUp(add)) >> >> >> >> Stephen >> > >> > . >> > >> _______________________________________________ >> swift-evolution mailing list >> [email protected] <mailto:[email protected]> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> _______________________________________________ > 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
