What is the advantage of nesting functions (generally speaking in Swift)

I am just learning Swift and I came across a section that talks about nesting functions:

Functions can be nested. Nested functions have access to variables declared in the outer function. You can use nested functions to organize your code into a long or complex function.

From here

So, if the intended benefit is "code organization", why not just nest the nested function independently of the outer function? It seems more organized to me.

The only advantage I can discern is that you "have access to variables declared in an outer function", but that seems trivial compared to the mess of having nested functions.

Any thoughts?

+3


source to share


3 answers


So, if the intended benefit is "code organization", why not just nest the nested function independently of the outer function? It seems more organized to me.

Oh, I totally disagree. If the only place the second function is required is inside the first function, keeping it inside the first function is much more organized.

Real life examples here: http://www.apeth.com/swiftBook/ch02.html#_function_in_function



In addition, a function within a function has a local environment in scope. Code inside a nested function can "see" local variables declared before the nested function is declared. This can be much more convenient and natural than passing multiple parameters.

However, the main thing that a local function allows you to do that you couldn't easily do in some other way is that you can form a function in real time (because a function is a closure) and return it from an external function.

http://www.apeth.com/swiftBook/ch02.html#_function_returning_function

+8


source


IMO, the only difference between closures and nested functions is recursion. You can pass a function directly into the function body without the trick.

func a() {
    func b() {
        b() // Infinite loop!
    }
    b()
}

      

The captured object of the reference type dies when the dying person dies. In this case, the capture is a function of the lexical scope. This means that the function will die when it finishes executing.

Technically, the reference loop does this and is usually discouraged. But it can be helpful if you use it wisely.



For example combine this with asynchronous operations.

func spawnAsyncOp1(_ completion: @escaping () -> Void) {
    enum Continuation {
        case start
        case waitForSomethingElse1
        case retry
        case end
    }
    let someResource = SomeResource()
    func step(_ c: Continuation) {
        switch c {
        case .start:
            return step(.waitForSomethingElse1)

        case .waitForSomethingElse1:
            DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(10), execute: {
                let fc = (someResource.makeRandomResult() % 100 < 50) ? .end : .retry as Continuation
                print("\(fc)")
                return step(fc)
            })

        case .retry:
            return step(.start)

        case .end:
            return completion()
        }
    }
    return step(.start)
}

      

It can simplify resource management in the execution of a coroutine without an explicit object instance. The resources are simply committed to the function spawnAsyncOp1

and will be released when the function dies.

0


source


It's nice that Xcode will nest the nested functions inside its parent function in the popup menu. The function popup menu is much easier to navigate with functions related to layout indentation and all grouped in one place.

image

0


source







All Articles