SE-0279: Multiple Trailing Closures [Amended]

Things like this could be "deprecated" using an @explicit attribute on the completion label:

func animate(withDuration duration: TimeInterval,
             animations: () -> (),
             @explicit completion: (Bool) -> ())

(This is what I was proposing on this other thread regarding single trailing closures.)

It'd would make the completion label mandatory. You'd only have these options for calling this function (or you get a warning):

UIView.animate(withDuration: 0.3) {
   self.view.alpha =0
} completion: {
   self.view.removeFromSuperview()
}
// or:
UIView.animate(withDuration: 0.3, animations: {
   self.view.alpha =0
}, completion: {
   self.view.removeFromSuperview()
})
// or (if we allow the first trailing closure to have a label):
UIView.animate(withDuration: 0.3) animations: {
   self.view.alpha =0
} completion: {
   self.view.removeFromSuperview()
}

So you'd be limited to all the options that actually make sense. ;-)

It'd also solve the Binding(get:set:) problem if you could make @explicit the two parameter labels.

Strictly speaking it's not source-breaking or backward-incompatible to make every label explicit by default if a failure to add the completion label only brings a warning (with a fixit). It'd just be deeply annoying because it'll happen for every call with a trailing closure where the closure parameter has a label... until the corresponding function signature is updated to make the label optional (where it makes sense).

That's probably fine for the standard library functions and I guess the Apple SDKs since they are updated in sync with the compiler. I assume Xcode's migration assistant would help too. Still, it'd be a disturbing change with a lot of trouble for everybody. Keeping the current behavior (optional label for the trailing closure) and adding a flag for when the label is required is easier and probably good enough, even though I think it's less in line with the language's principles.

I also tend to agree it'd be better if the label could not be omitted as a default behavior, but I disagree that the behavior should be different from the single trailing closure case. In particular, if we add mechanism like the @explicit attribute to prevent a label from being omitted as a single closure, it'd be quite awkward that we also had to add an @implicit attribute to allow a parameter label to be omitted in the multiple closure case.

1 Like