The capture list would turn into property declarations, initialized in a memberwise fashion with the values that were captured.
Captures would be by value, so sharing would only happen when the captured value has reference semantics.
Boxing would not necessarily happen. From the compilerās point of view the instance of the anonymous struct that gets passed would be no different than an instance of a nominal struct. Depending on how the optimizer handles the code the value may or may not get boxed.
I realize I didnāt share a complete example of what the de-sugaring might look like. I think that might help explain the idea. So, the Monoid
example above would de-sugar as follows:
[1, 2, 3].fold {{ [empty = 0] in $0 + $1 }}
becomes
struct SomeNameUsedByTheCompiler: Monoid {
let empty = 0
func combine(_ lhs: Int, _ rhs: Int) -> Value { lhs + rhs }
}
[1, 2, 3].fold(SomeNameUsedByTheCompiler())
And the SwiftUI example above would de-sugar as follows:
NavigationLink("Details") {{
VStack {
// details view content
}
}}
becomes:
struct SomeNameUsedByTheCompiler: View {
var body: View {
// details content view
}
}
NavigationLink(āDetailsā, destination: SomeNameUsedByTheCompiler())
So hereās a final example with a mutating method requirement:
protocol Foo {
associatedtype Bar
mutating func update(with value: Bar)
}
aFunctionTakingFoo {{ [var count = 0] (value: Int) in
count += value
}
De-sugaring to:
struct SomeNameUsedByTheCompiler: Foo {
var count = 0
mutating func update(with value: Int) {
count += value
}
}
aFunctionTakingFoo(SomeNameUsedByTheCompiler())
Does this help explain how the de-sugaring would work?
IMO, the explicit name and boilerplate required for a single-use / ad-hoc nominal struct are significant enough to be annoying. This is especially the case when lexical distance is necessary (i.e. a local struct is not possible in the current lexical context). These syntactic issues can unnecessarily complicate code that should be simple and can discourage some library design choices that would otherwise be viable.