In this question I saw today It defines a struct Effect
that has a property run
that is a closure that takes a Generic parameter:
struct Effect<T> {
let run: (@escaping (T) -> Void) -> Void
}
Then the sample code creates an instance of Effect<Int>
, and specifies the closure for the run
property with something that looks like trailing closure syntax:
let anIntInTwoSeconds = Effect<Int> { callback in
DispatchQueue.main.asyncAfter(deadline: .now() 2) {
callback(42)
}
}
What makes that legal? I would expect to need to specify the run parameter explicitly in a call to the init method:
let anIntInTwoSeconds = Effect<Int>(run: { callback in
DispatchQueue.main.asyncAfter(deadline: .now() 2) {
callback(42)
}
}
)
Either version compiles and works. What in Swift makes that first version legal? I couldn't figure out how to frame the question so that I could search for an answer.
CodePudding user response:
This works just like any function whose last parameter is a function. Trailing closure syntax is trailing closure syntax. The fact that the function is an initializer changes nothing.
So let me build up to it in stages. You know you can say:
func myfunc(whatever: () -> ()) {}
myfunc {}
Okay, but now let's make it a static method:
struct S {
static func myfunc(whatever: () -> ()) {}
}
S.myfunc {}
OK, but init
is a static method — it's just a static method whose name you are allowed to omit:
struct S {
let whatever: () -> ()
}
S {} // meaning S.init {}