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

Víctor Pimentel Rodríguez vpimentel at tuenti.com
Wed Jun 7 18:14:59 CDT 2017

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/915e0
> 0fa6d1e59d58cd8c38dd6dc83765fc67fe4
> 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 }


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

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.

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."

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.

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
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).
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/20170608/c8d7711c/attachment.html>

More information about the swift-evolution mailing list