[Accepted] SE-0279: Multiple Trailing Closures

This raises a question for me: How do we correct past mistakes?

Well, we have a pitch and review process to try to avoid them from the beginning, but as in this case one is always wiser after the event. There ought to be a way to correct past mistakes or is that ruled out forever by the stable ABI law? Any thoughts on this?


The core team was not entirely satisfied with the basic design of single trailing closures, and now we have multiple trailing closures with a design that no one seems entirely satisfied with :thinking:.

I don't get why so much time and effort is being spent on something like this, it's just more syntax, making the language more complicated, not more powerful.


I too am surprised (in a bad way) that the proposal was accepted “as is”. Personally, I am for breaking source compatibility from time to time instead of piling up warts.

(This acceptance post reminds me of the “callAsFunction” fiasco where we ended up with the worst of all worlds. It also reminds me of the time when we lost closure labels; they were supposed to come back soon. And yet, here we are. One wart, two warts, three.)


Maybe we'll find out at WWDC2020?


It'd be nice if Xcode had an alternate shortcut key to complete this without the trailing closure syntax.


I don't get the point why special annotation is required if the first labeled closure is treated as same as other trailing closures. Maybe it's required for source compatibility that I can't fully understand how it works now.

I hope someday when we find the label for the first closure is also important, I will be able to write

  get: { ... }
  set: { ... }

instead of

  get: { ... }
  set: { ... }
1 Like

I don't think we need to turn announcement into post-review review thread.


I was about to say the same thing.

It might not have been necessary for the language to move forward, but I'm sure there were a few WWDC talks that were held up by it.


Dear core team, this feature is new and called "multiple trailing closures", it does not have to be consistent with the "single trailing closure"! We already had such example with "multiline string literal" vs. "single line string literal" where the former has its own set of rules. It would be great if we‘d rather deprecate the single trailing closure rules over time in favor of at least consistent and symmetrical rules for the multiple trailing closures, which can and should be reducible to a single closure.

I have a few more things to say:

  1. The proposal should have returned to the pitch state after the first review, but it didn‘t which lead us to this.
  2. We now have a really bad habit to spawn proposals around WWDC, and accept them no matter what regardless potentially flawed designs. This seems to repeat for several years now.
  3. I‘m strongly upset that my feedback and from many others during the proposal reviews was counted as positive regardless the clearly communicated "only if" requirement for the first trailing closure label. I would like officially revert my review voice into a vote against the overall proposal.

Thank you for reading my feedback.


IIRC, it was brought up during the review that requiring first label would lead to a (different, but also relatively) easy rule. Something along the line of "labels are required, but if you have only one closure, it can be dropped".


Nobody's opinion was considered to be positive if they said that they wanted an argument label on the first closure. The post says quite plainly that "[o]ther reviewers... felt that it was not tenable without allowing an argument label on the first closure". That sentence could certainly be more explicit about including people who wanted the label to be required, but it does include them, and (more importantly) that is how we actually treated such feedback: as negative.

However, Swift evolution is not a consensus process, or even a majoritarian one. The core team receives feedback that it disagrees with on essentially every single proposal, and it makes the decisions it makes anyway. You are welcome to disagree with those decisions, but that fact that you disagree does not mean that your feedback was ignored.


That's why I only rarely participate in review threads these days. Why put the effort in when your opinion (and even the community's consensus opinion) means so little to the eventual outcome?


The community did not express a consensus opinion against this proposal by any means. And the community's opinion actually caused the proposal to be radically revised. But people tend to come up with arguments for why the process was flawed whenever they don't like the result.


Controversial proposals are accepted all the time, but this kind of backlash is rare (a glance in this thread for a quick poll shows 2 likes for the acceptance post, against 25-30 for dissenting opinions). So your argument that I'm just rationalising an unfavourable result seems rather unfair.


I'm still wrapping my head around this, but I want to be positive. The way I interpret the following:

is that we should consider "Swifty" to design APIs in that way. It's ok, and I like when clear direction is given about how to use the language.

But I have a pragmatic question, now. Consider the aforementioned fold function on Result:

extension Result {
  func fold<A>(onSuccess: (Success) -> A, onFailure: (Failure) -> A) -> A {
    switch self {
    case let .success(x):
      return onSuccess(x)

    case let .failure(x):
      return onFailure(x)

I don't want to discuss the utility of this (I consider it essential, it should be in the stdlib), but the ergonomics: with the new guidelines, what is a better way to write this? It's a serious question: given the guidelines, what kind name for this would be recommended? Incorporating the onSuccess label in the function root name would be terrible, that's not an elegant solution, but what would be? I suspect a possible solution would drop the symmetry between the branches in some way, but I can't come up with anything decent.


I'm not disputing that there's a negative response to the decision. I'm saying that the negative response is chiefly because people want to be able to write a label on the first trailing closure (or to require it), not because there's a pervasive flaw in the process. People disagree with the decision.

1 Like

I'd like to add some feedback about the review process. I did realised for a few reviews already that they are rarely about the votes or consensus. Rather, it's more of an inquiry about the pros & cons of the design, and the information that the decision makers may have missed, and should find useful.

Often times the reviews quickly devolved into defending my idea/design kind of discussion. It is not necessarily a bad thing. Designs that help shape the final product do come up relatively frequently, but it usually adds very little to the proposal past certain point. And the alternate design discussion is usually very taxing for everyone involved, including those who're planning on chiming in. There is one portion of this review that discussed about the near-ambiguity against existing call syntax. I very much noticed that that's the very information that the review needs, even without the core team's affirmation.

If my assessment above is at least somewhat inline with the spirit of the process. I think that, as is, it isn't being conveyed very well.

I think the the semi-announcement at the end of the thread, that the information has been gathered, is very helpful. Especially that we have been employing a light touch to the review deadline. More so if it takes some time until the review announcement.


This is unfair. It is a well-known human trait to be silent when the outcome is agreeable. The fact that more people are voicing dissent at this time is not a strong indicator.


Why is it an issue to allow the average Swift user to write the first closure label explicitly and still support its optionality for source compatibility? This would allow you to observe the preferred option over time and potentially signal a deprecation need of the optionality. At least it wouldn‘t break anything and certainly not cause more damage by spawning more proposals to force firstWhere naming scheme on us.


Previous accepted proposals don't show that pattern.

And some would argue that when such an unpopular proposal makes its way in to the language despite strong opposition from those that use it, that itself is evidence of a flawed process.

But I've said all I want to say on this.