Great catch! I didn’t know that was possible! I’ll add it to the proposal. Thanks!
- Dennis > On May 30, 2016, at 3:53 PM, Vladimir.S <[email protected]> wrote: > > I believe you should add currently available syntax to proposal text: > > let c = zip(a,b).reduce(0) { (acc, tuple: (a: Int, b: Int)) in > acc + tuple.a + tuple.b > } > > func takesATuple(tuple : (valueA: Int, valueB: Int)) { > print("a: \(tuple.valueA) b:\(tuple.valueB)") > } > > Not so nice as proposed, but not so ugly as just tuple.0. > I'm not sure if the proposed feature is adding important improvement to the > language. > > On 30.05.2016 0:20, Dennis Weissmann via swift-evolution wrote: >> Thanks for everyone participating in this discussion! :) >> I’ve drafted a formal proposal, it is available >> here: >> https://github.com/dennisweissmann/swift-evolution/blob/tuple-destructuring/proposals/0000-tuple-destructuring.md >> >> Please let me know what you think (it would be great if a native speaker >> could take a look at grammar and spelling mistakes). Thanks! >> >> >> Tuple Destructuring in Parameter Lists >> >> * Proposal: SE-NNNN >> >> <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md> >> * Author(s): Dennis Weissmann <https://github.com/dennisweissmann> >> * Status: *Awaiting review* >> * Review manager: TBD >> >> >> Introduction >> >> Tuple destructuring is the process of extracting elements from tuples. >> >> This is valid today: >> >> Swift >> >> |let point = (x: 20.0, y: 31.0, z: 42.0) // Approach 1: let x = point.x let >> y = point.y let z = point.z // Approach 2: let (x, y, z) = point // For-in >> loops support tuple destructuring for (x, y, z) in [point] { // use x, y, z >> }| >> >> Swift-evolution thread: [Pitch] Tuple Destructuring in Parameter Lists >> <http://thread.gmane.org/gmane.comp.lang.swift.evolution/16190> >> >> >> Motivation >> >> This proposal seeks to generalize this behavior for every use case where >> tuples need to be destructured. These are parameter lists in closures and >> parameter lists in functions. Consistency is a major goal of Swift but it >> is currently only possible to destructure tuples in the above mentioned >> places. >> >> >> Proposed solution >> >> Extending tuple destructuring to parameter lists seems natural and improves >> consistency in the language. >> >> >> Closures >> >> Parameters in closures are currently not directly destructable. They can >> either be accessed via |.0|, |.1|, etc. or can be destructured by assigning >> them to variables in an explicit statement. >> >> It feels natural to do this right in the parameter list itself (just like >> with for-in loops). >> >> Swift >> >> |let a = [0,1,2,3,4,5,6,7,8,9] let b = [0,1,2,3,4,5,6,7,8,9] // Allowed >> today: let c = zip(a,b).reduce(0) { acc, tuple in acc + tuple.0 + tuple.1 } >> // Also allowed today: let c = zip(a,b).reduce(0) { acc, tuple in let >> (valueA, valueB) = tuple return acc + valueA + valueB } // Proposed syntax: >> let c = zip(a,b).reduce(0) { acc, (valueA, valueB) in acc + valueA + valueB >> }| >> >> >> Functions >> >> When it comes to functions this proposal uses Swift's feature of >> differentiating between internal and external parameter names. >> >> Swift >> >> |// Allowed today: func takesATuple(tuple: (Int, Int)) { let valueA = >> tuple.0 let valueB = tuple.1 // ... } // Proposed syntax: func >> takesATuple(tuple (valueA, valueB): (Int, Int)) { // use valueA // use >> valueB }| >> >> This design has no visible effects to the call site of a function but makes >> it very convenient for the function author to use the tuple's elements >> inside the function body. >> >> >> Impact on existing code >> >> This feature is strictly additive and does not effect current code. >> >> >> Alternatives considered >> >> Leave it as is destructure in a separate assignment. >> >> >> >> - Dennis >> >>> On May 11, 2016, at 10:12 AM, Dennis Weissmann via swift-evolution >>> <[email protected] <mailto:[email protected]>> wrote: >>> >>> Thanks for all your feedback! >>> >>> This is the current statistic: >>> Closure syntax: All positive >>> Function syntax: 3 (or 4) positive, 2 negative >>> >>> I’ll try to address the concern Geordie and T.J. have. >>> >>>> func takesATuple(someInt: Int, tuple: (valueA: String, valueB: String)) {} >>> >>>> It’s true that you still have the ‚overhead‘ of having to >>>> type /tuple./ before accessing its members. But this is almost always >>>> what I want (hopefully you’d never actually name your tuple ‚tuple‘, >>>> instead it’d be a logical namespace for what it contains). Do you have a >>>> real-world example where you’d need this? To me it seems that in a case >>>> like this the API that produced the tuple would need refining rather >>>> than the language itself. >>> >>> What you suggest here is not tuple destructuring but using labeled >>> tuples. And while I’m totally with you that this is for many cases the >>> better approach, I still think we should introduce it to functions as >>> well, for consistency and readability reasons. >>> In the end inconsistency is what led to this thread because tuple >>> destructuring is already possible today - in for loops: >>> >>> letstringTuple = [("", "”), ("", "")] >>> for(i, j) instringTuple {} >>> >>> That made me wonder if it’s also possible for closures (because I needed >>> it there - and eventually someone will definitely wonder if it’s possible >>> for function arguments as well). >>> >>> You also asked me for my use case. To be honest, I don’t have one for the >>> function version, but imagine the following: >>> >>> My current closure use case is this >>> (template.points and resampledPoints are of type [CGPoint]): >>> >>> letlocalHighestSimilarity = zip(template.points, >>> resampledPoints).reduce(0.0) { accumulator, points in >>> let(template, resampled) = points >>> returnaccumulator + Double(template.x* resampled.x+ template.y* >>> resampled.y) >>> } >>> >>> To reuse this code elsewhere I maybe want to refactor the closure into a >>> function (using your labeled tuple suggestion): >>> >>> funcaccumulateSimilarity(accumulator: Double, for points: (point1: >>> CGPoint, point2: CGPoint)) -> Double{ >>> returnaccumulator + Double(points.point1.x* points.point2.x+ >>> points.point1.y* points.point2.y) >>> } >>> >>> This isn’t particularity readable (image passing a CGRect and you need >>> the points or a more complex calculation). Compare it to this: >>> >>> funcaccumulateSimilarity(accumulator: Double, for (point1, point2): >>> (CGPoint, CGPoint)) -> Double{ >>> returnaccumulator + Double(point1.x * point2.x + point1.y * point2.y) >>> } >>> >>> You can of course still pass a named tuple instead of an unnamed, but it >>> doesn’t make any difference, which brings me to an aside*. >>> >>> I think the second approach makes the calculation much more >>> comprehensible and it just feels “intuitive” (again, at least for me) :). >>> >>> >>> - Dennis >>> >>> * I’m not sure how scientifically correct the following statement is but >>> strictly speaking (at least for me) (valueA: String, valueB: String) is >>> not of the same type as (String, String) just like func d(string: String, >>> int: Int) is different from func e(_: String, _: Int) though in Swift the >>> tuples are interchangeable (you can pass one where the other is expected). >>> >>>> On May 8, 2016, at 6:10 PM, Geordie J <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>> Comments below >>>> >>>>> Am 05.05.2016 um 20:22 schrieb Dennis Weissmann via swift-evolution >>>>> <[email protected] <mailto:[email protected]>>: >>>>> >>>>> Following a short discussion with positive feedback on >>>>> [swift-users](http://thread.gmane.org/gmane.comp.lang.swift.user/1812) >>>>> I’d like to discuss the following: >>>>> >>>>> Tuples should be destructible into their components in parameter lists. >>>>> >>>>> Consider the following code: >>>>> >>>>> let a = [0,1,2,3,4,5,6,7,8,9] >>>>> let b = [0,1,2,3,4,5,6,7,8,9] >>>>> >>>>> let c = zip(a,b).reduce(0) { acc, tuple in >>>>> acc + tuple.0 + tuple.1 >>>>> } >>>>> >>>>> tuple is of type (Int, Int). >>>>> >>>>> The problem is that the calculation is not very comprehensible due >>>>> to .0 and .1. That’s when destructuring tuples directly in the >>>>> parameter list comes into play: >>>>> >>>>> let c = zip(a,b).reduce(0) { acc, (valueA, valueB) in >>>>> acc + valueA + valueB >>>>> } >>>> >>>> +1 I think this is a great way to go about it. >>>> >>>>> >>>>> The above is what I propose should be accepted by the compiler (but >>>>> currently isn’t). >>>>> >>>>> Currently tuple destructuring is possible like this: >>>>> >>>>> let c = zip(a,b).reduce(0) { (acc, tuple) in >>>>> let (valueA, valueB) = tuple >>>>> return acc + valueA + valueB >>>>> } >>>>> >>>>> This is not about saving one line ;-). I just find it much more >>>>> intuitive to destructure the tuple in the parameter list itself. >>>> >>>> Agreed >>>> >>>>> >>>>> The same thing could be done for functions: >>>>> >>>>> func takesATuple(someInt: Int, tuple: (String, String)) >>>>> >>>>> Here we also need to destructure the tuple inside the function, but the >>>>> intuitive place (at least for me) to do this would be the parameter list. >>>>> >>>>> In the following example I'm making use of Swift’s feature to name >>>>> parameters different from their labels (for internal use inside the >>>>> function, this is not visible to consumers of the API): >>>>> >>>>> func takesATuple(someInt: Int, tuple (valueA, valueB): (String, String)) >>>> >>>> >>>> I’m not such a fan of this though. I realize what I’m about to write >>>> here is discussing a slightly different point but bear with me: I was >>>> under the impression it was already possible to do something like this >>>> (maybe only possible with typealiases): >>>> >>>> func takesATuple(someInt: Int, tuple: (valueA: String, valueB: String)) {} >>>> >>>> I find that syntax readable and extensible: you can make a type alias >>>> for your tuple type '(valueA: String, valueB: String)‘, you can then use >>>> it like this: >>>> >>>> func takesATuple(someInt: Int, tuple: MyAliasedTupleType) { >>>> print(tuple.valueA) >>>> } >>>> >>>> It’s true that you still have the ‚overhead‘ of having to >>>> type /tuple./ before accessing its members. But this is almost always >>>> what I want (hopefully you’d never actually name your tuple ‚tuple‘, >>>> instead it’d be a logical namespace for what it contains). Do you have a >>>> real-world example where you’d need this? To me it seems that in a case >>>> like this the API that produced the tuple would need refining rather >>>> than the language itself. >>>> >>>>> >>>>> Here valueA and valueB would be directly usable within the function. >>>>> The tuple as a whole would not be available anymore. >>>>> >>>>> >>>>> Now it’s your turn! >>>>> >>>>> 1. What do you think? >>>>> 2. Is this worth being discussed now (i.e. is it implementable in the >>>>> Swift 3 timeframe) or should I delay it? >>>>> >>>>> Cheers, >>>>> >>>>> - Dennis >>>>> _______________________________________________ >>>>> swift-evolution mailing list >>>>> [email protected] <mailto:[email protected]> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> >>> _______________________________________________ >>> 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
