0

I've come across this strange closure usage in the link

The below code is a simplified version in Xcode Playground

typealias AppStateDeeplinkAction   = () -> ()

var deeplinkBlock : AppStateDeeplinkAction? = {
    print ("this is for deeplink")
}

func deeplinkAction() {
    if let deeplinkAction = deeplinkBlock {
        print("deeplink is executed")
        deeplinkAction() // <- if this is commented out, the result is just "deeplink is executed"
    }
}

deeplinkAction() 

The result of this is,

deeplink is executed
this is for deeplink

What's confusing is, deeplinkAction() func is called inside the if-let and there is no compile/run time error. It ended up successfully. What I don't get quite is the recursive call of deeplinkAction().

Compared to this, if deeplinkAction() is commented out, the result is just

deeplink is executed

What kind of 'closure' feature am I missing? How should I interpret this?

Eric
  • 754
  • 6
  • 5
  • 1
    I would name them different, the `if let`: `if let other = deeplinklBlock { print... other() }`. It's the same when you do an `if let` and you name it the same as the var. It might be confusing, and might be too bad discouraged here to have the method named as the var. – Larme Nov 26 '20 at 17:34
  • Yes, it's clear to me now. Thanks a lot~ – Eric Nov 26 '20 at 18:16

1 Answers1

2

There's no recursive call here, but using the same name for an optional binded closure variable as for the enclosing function is misleading and hence a bad idea.

Simply rename it and everything will be clear. The parentheses after a closure variable execute said closure, so deeplinkBlock() execute the closure stored in the deeplinkBlock variable.

typealias AppStateDeeplinkAction = () -> ()

var deeplinkBlock : AppStateDeeplinkAction? = {
    print ("this is for deeplink")
}

func deeplinkAction() {
    if let deeplinkBlock = deeplinkBlock {
        print("deeplink is executed")
        deeplinkBlock()
    }
}

deeplinkAction() 

Actually, there's no need for the optional binding anyways, you can use optional chaining on closures too.

func deeplinkAction() {
    deeplinkBlock?()
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116