Support use of an optional label for the first trailing closure

Food for thought outside the scope of this excellent proposal:

I've found little or no discussion of trailing-closure syntax in the context of memberwise initialization of structs with closure properties. By way of example, this sort of syntax regularly arises in the context of SwiftUI:

struct InsetView<Content>: View where Content: View {
    let leadingInset: CGFloat
    let trailingInset: CGFloat
    var content: () -> Content

    var body: some View {
        ...
    }
}

The synthesized memberwise initializer for this struct uses each property name as the parameter name. At the call site, we have:

InsetView(leadingInset: 10, trailingInset: 10) { 
    ...
}

If labels become required on the first trailing closure, initializing the struct would look like this:

InsetView(leadingInset: 10, trailingInset: 10) content: { 
    ...
}

The label feels out of place. Why?

Answer

Because the type was designed with an unlabelled trailing closure in mind.

Of course, in this hypothetical world of required label names, the solution to a bothersome label likely would be to expressly declare an initializer for the struct with an explicitly omitted argument label for the closure parameter.

init(leadingInset: CGFloat, trailingInset: CGFloat, _ content: @escaping () -> Content) {
    self.leadingInset = leadingInset
    self.trailingInset = trailingInset
    self.content = content
}

Unfortunately, that solution would come at the expense of losing the efficiency and minimalist look and feel attendant to synthesized memberwise initializers.

On the subject of a more granular approach to memberwise initializers, see Explicit Memberwise Initializers.

2 Likes