Home > Mobile >  How can you initialize a struct with a closure parameter like this?
How can you initialize a struct with a closure parameter like this?

Time:11-21

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 {}
  • Related