WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

Function vs. Closure comparison advantages

Forums > 100 Days of SwiftUI

I'm a bit confused as to the usefulness of closures. In the following code, what advantage (if any) does the constant greetFrench have over the function greetEnglish? Or is this just too simple a case to show the usefulness of closures?

func greetEnglish(_ name: String) -> String {
    return "Hi \(name)!"
}

let greetFrench = { (_ name: String) -> String in
    "Bonjour \(name)!"
}

struct ContentView: View {
    var body: some View {
        VStack{
            Spacer()
            Text(greetEnglish("Bob"))
            Spacer()
            Text(greetFrench("Bob"))
            Spacer()
        }
    }
}

1      

Both are functions

Both of these are functions. The second one is sometimes referred to as an anonymous function. It's anonymous because it doesn't have a name. Yet, it does the same thing.

// named function
func greetEnglish(_ name: String) -> String {
    return "Hi \(name)!"
}

// anonymous function
{ (_ name: String) -> String in
    "Bonjour \(name)!"
}

You're on to something though. Your example shows the technique of writing a closure. But there is little to no value in performing the greeting one way or the other. So let's find another example.....sorting and printing array data.

// Paste into Playgrounds
let quizScores = [ 77, 87, 99, 40, 98, 98, 76, 88, 42] // not bell shaped!
quizScores.sorted()  //  results: [40, 42, 76, 77, 87, 88, 98, 98, 99]

There is a natural way to sort integers. Nice and easy. Now try something weird.
In the code below, both the sorted() and the forEach() statements use functions. Really short functions. You could write out full code for these. Think of clever function names, sortNPC(by:), or printNPCjustName(npc:). But in code like this, it may not be worth the effort.

struct OrcWarrior {
    let name: String
    let age: Int
    let wisdom = 0  // orc, amirite?
    let strength: Int
}
// create an array of NPCs
let nonPlayingCharacters = [
    OrcWarrior(name: "Bluto",  age: 233, strength: 12),
    OrcWarrior(name: "Popeye", age: 120, strength: 42),
    OrcWarrior(name: "Brutus", age: 190, strength: 38),
    OrcWarrior(name: "Olive",  age:  21, strength:  6)
]
// Four different functions required in the code below!
print("--- by age")
nonPlayingCharacters.sorted{ $0.age < $1.age }.forEach{print($0.name)}
print("--- by strength")
nonPlayingCharacters.sorted{ $0.strength > $1.strength }.forEach{print($0.strength & ": " & $0.name)}

So, in this simple case, anonymous functions (aka closures) provide the functionality I need. But now I don't have to write out four (!) fully defined, named functions with descriptive parameters names and return types. You'll find more uses for closures as you progress!

2      

Hacking with Swift is sponsored by Emerge

SPONSORED Optimize your app’s startup time, binary size, and overall performance using Emerge’s advanced app optimization and monitoring tools. Reliably measure app size, speed up your app's startup time with Emerge's Launch Booster, and much more. Emerge is actively used by many of the top mobile development teams in the world.

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.