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

Xiaodi Wu xiaodi.wu at gmail.com
Wed Jun 7 21:33:17 CDT 2017


On Wed, Jun 7, 2017 at 19:15 Víctor Pimentel Rodríguez <vpimentel at tuenti.com>
wrote:

> On 7 Jun 2017, at 21:29, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
>
> SE-0110 may be an obvious extension of the proposed goal, but it is clear
>> that it has been implemented in Swift 4, and that the consequences are
>> derived of those changesets.
>>
>> Those "unwanted" consequences can be reverted by temporarily reverting
>> SE-0110, without touching any other previous proposal.
>>
>> In no place I see Gwendal asking for full reversal of 5 proposals. He is
>> just voicing something that a lot of app developers and library maintainers
>> are not going to understand in September.
>>
>> For example, you can see all the changes needed in RXSwift so that it
>> compiles to Swift 4:
>>
>> https://github.com/ReactiveX/RxSwift/pull/1282/commits/
>> 915e00fa6d1e59d58cd8c38dd6dc83765fc67fe4
>>
>> I would not want to migrate to Swift 4 an app using such framework.
>>
>> I asked you in my first reply to you, is your view that the distinction
>> itself between (Int, Int) -> Int and ((Int, Int)) -> Int is problematic? If
>> so, this is a very different discussion from seeking solutions to mitigate
>> particular ergonomic issues that arise from the change. However, you have
>> not answered the question.
>>
>>
>> As far as I can see, the bigger usability regressions are caused when
>> using generics, specially in collections and functional utilities. When you
>> specify that type with a tuple, as in Dictionary, then all the related
>> methods start receiving closures receiving tuples.
>>
>> Notice that allowing some syntactic sugar on the call site of those
>> closures may not be enough, since you may have stored or passed a closure
>> for customization purposes.
>>
>
> Can you illustrate this with an example? I’m not sure I understand what
> you’re getting at here.
>
>
> Sure. Let's say you want to filter some elements from a dictionary, and
> you have this valid Swift 3 code:
>
> let conversationsById: [String: Conversation]
> let unreadConversations = conversationsById.filter { $1.isUnread }
>
> Or:
>
> let unreadConversations = conversationsById.filter { id, c in
>     return !id.isEmpty && c.isUnread
> }
>
> Neither of these expressions are permitted in Swift 4, but some syntactic
> sugar can be added to allowing it again without the need of full tuple
> splatting.
>

Right.

However, if for some reason you want to pass around a filter closure, you
> will still have mismatch types:
>
> func first(passing filter: (String, Conversation) -> Bool) ->
> Conversation? {
>     return conversationsById.filter(filter).first?.value
> }
>

> This example is simple and useless and contrived, but it gets even worse
> when you take generics into account to catch any type of closure.
>

I’m not going to raise any issues over how realistic the scenario might be.
It's for answering a question, after all.

However, what I don’t get is why you’d have a mismatch here. Your method
`first` accepts a closure, and surely the type it expects should be
`((String, Conversation)) -> Bool` instead, since that is the type that the
`filter` method expects in the body of your implementation?

Certainly, there are scenarios not possible (or at least, very difficult)
without tuple splatting, but that’s straight-up an argument for tuple
splatting. That's, IMO, an unnecessary argument, since the usefulness of
the feature has never been in question, only the resources to design and
implement.

This behavior is so hurtful to functional style programming, that I think
>> either SE-0110 should be reverted, or alternatives like this Susan proposal
>> should be implemented.
>>
>
> To be clear, what you and Gwendal are objecting to is the loss of tuple
> splatting, is it not? Again, SE-0110 is only the final piece; SE-0029 is
> what removed implicit tuple splatting. As that proposal said, a properly
> designed explicit tuple splatting can be considered if there’s demand, and
> it was understood that removing this functionality would be a regression
> and nonetheless the decision for removal was still deliberately undertaken.
> Re-reading that proposal, the rationale was that it never worked correctly
> to begin with, and the barrier for bringing it back is that it requires
> considerable effort to design and implement the feature correctly.
>
> I'm sorry if there has been any disrespect for my part, I appreciate what
> you all do here. But sometimes it's a bit frustrating having to explain why
> something that seems obvious to us is not obvious to others.
>
> I think that you have a bigger picture from the Swift Evolution point, but
> the thing is that Swift users like me doesn't have that context, and we are
> baffled when we encounter that some pretty simple code turns into a weird
> thing in a migration. I have linked to several real examples out there, and
> it seems to be a popular opinion. Nevertheless, it was Tony Parker's mail
> the one that kindled this discussion with a really simple question.
>
> It may be the last piece, but it is the piece that impacted simple code
> the most, or at least the one that had the most unexpected consequences.
> Certainly that proposal does not contain nearly enough code examples or
> goes deeply enough. And this is subjective, but for me this isn't true:
> "Minor changes to user code may be required if this proposal is accepted."
>

SE-0110 is short not because there wasn’t thought devoted to the change but
because that thought was largely already undertaken elsewhere (for example,
in SE-0029). As far as I can tell, the only part of SE-0110 that actually
required review as a proposal was the double-parenthesis syntax for a
single argument of tuple type; beyond that, I cannot understand how SE-0029
could be considered implemented without implementing SE-0110.

The fact that it affects even the standard library shows how hurtful
> removing this feature is. It's not a nice-to-have feature or a
> somewhat-useful feature, it's that right now it's very difficult to model
> something as essential as Dictionary with a nice-to-use API. So lots of
> other custom types will suffer too.
>

I think “very difficult” is a stretch; suffice it to say that it’s a step
back in ergonomics that may disproportionately affect certain programming
styles.

If we all agree that this is a loss of ergonomics, then the Core Team have
> several options for Swift 4:
>
> 1. Do nothing.
> 2. Revert SE-0110 related changes.
> 3. Add a complex tuple-splatting feature.
> 4. Add some syntactic sugar keeping the same syntax.
> 5. Add some syntactic sugar but changing the syntax.
>
> For me:
>
> 1. I want to avoid this, and I think Gwendal and others too.
> 2. I know nothing about how it was implemented, but for the time being it
> would be the best option for me, as it would avoid painful migrations where
> you are forced to make your code worse. But if it's too difficult to do, I
> understand.
> 3. No time for this.
> 4. Probably no time for this, and I don't think it would not cover all the
> regressions (like the example of passing a closure).
>

My point is that some (many?) of the regressions are intentional (i.e. loss
of implicit tuple splatting generally); Gwendal and others may not like it,
but that's not grounds for disputing an approved proposal. The aim of the
conversation should be focusing on the regressions that are
_unintentional_, since unintentional consequences do represent grounds for
revisiting a proposal. Pervasively littering `$0.0` inside closures was not
foreseen (or at least discussed, as far as I recall), and that can be
mitigated by allowing tuple destructuring in the closure parameter
shorthand, whether with new syntax or not. A complete implementation of
this feature has never actually existed in Swift, but it would certainly be
useful.

There is no need to speculate as to whether it would be replaced in future
version of Swift; if it is useful enough to be included now, it should be
included for all time; otherwise, it should not be included at all.

5. It will also hurts a bit the ergonomics, but more importantly it will
> hurt the migrations. And this will probably be replaced in next versions of
> Swift, so it's very suboptimal, I think.
>
> Anyway, I may disagree with the result, but if it's what the Core Team
> wants or needs then ¯\_(ツ)_/¯
>
> --
> Víctor Pimentel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170607/73c90771/attachment.html>


More information about the swift-evolution mailing list