Understanding syntax of closure with no return type

1.9k Views Asked by At

I am getting into swift for the first time here and I have stumbled across a closure statement that doesn't make a whole lot sense to me based off of my current understanding of how closures are written. This is really a two-part question because I also don't quite grasp the intention/interpretation behind the conditional binding with this closure.

The chunk of code I am thrown by is this:

 FIRAuth.auth()?.createUser(withEmail: email, password: password) {
    (user, error) in if let error = error {
        print(error.localizedDescription)
        return
    }
}

My understanding is that the closure needs specify a return type based off of the docs definition (something1, something2) -> () so from the bit of code above, does that just mean that swift can infer a void return by not including the -> ()?

My assumption is that the conditional binding statement just says 'if an error arg is passed into this closure, then print the error?

Please use as much detail as possible in your explanation as possible so I can further my understanding. Cheers!

2

There are 2 best solutions below

5
On BEST ANSWER

The following are all equivalent

func foo1() -> () { }
func foo2() -> () { return () }
func foo3() -> () { return Void() }
func foo4() -> () { return }

func foo5() -> Void { }
func foo6() -> Void { return () }
func foo7() -> Void { return Void() }
func foo8() -> Void { return }

func foo9() { }
func foo10() { return () }
func foo11() { return Void() }
func foo12() { return }

print(type(of: foo1))  // (()) -> ()
// ...
print(type(of: foo5))  // (()) -> ()
// ...
print(type(of: foo9))  // (()) -> ()
// ...

If no return type is supplied to a function(/closure), then the empty tuple type (which is typealiased by Void) is inferred. We may, however, explicitly supply this return type, either as () (the type), or Void. From the language guide - functions:

Functions Without Return Values

Functions are not required to define a return type. ...

...

Strictly speaking, this version of the greet(person:) function does still return a value, even though no return value is defined. Functions without a defined return type return a special value of type Void. This is simply an empty tuple, which is written as ().

Conversely, if no return is given at the end of a function block, it will be the same as explicitly returning an instance of the empty tuple, namely () (the value). This may also be written simply as return.

1
On

() is the empty tuple. Void in Swift is just a type alias to (). If a function or closure doesn't specify a return type, then () is assumed.

To avoid confusion, the (user, error) in should be on its own line:

 FIRAuth.auth()?.createUser(withEmail: email, password: password) { user, error in
    if let error = error {
        print(error.localizedDescription)
        return
    }
 }

I'd suggest using a guard statement to enforce an early return:

 FIRAuth.auth()?.createUser(withEmail: email, password: password) { user, error in
    guard error == nil else {
        print(error!.localizedDescription)
        return
    }

     // There's no error, carry on...
 }