Day 6 - 100 Days of Swift

2 minute read

Closures (part 1)

Day 6 is about closures. You look at creating basic closures, accepting parameters to them, and returning values from them. You also look at passing closures as a parameter and trailing closure syntax. Not a lot of content today, but I am guessing that is because closures are sometimes hard for people to grok.

Like functions, closures are blocks of code that you can call from other parts of your code. They don’t have names though, so they are often stored in variables. A basic one looks like this:

1
2
3
4
5
let sayHi = {
    print("Hi!")
}

 sayHi() // Prints: "Hi!"

You can accept parameters in closures just like you can in functions. You don’t get parameter labels with closures though, and they are defined within the definition of the closure itself, separated by the in keyword:

1
2
3
4
5
let sayHello = { (name: String) in
    print("Hello \(name)!")
}

sayHello("Abed") // Prints: "Hello Abed!"

You can also return values from closures:

1
2
3
4
5
let sayWhatsUp = { (name: String) -> String in
    return "What's up \(name)?"
}

sayWhatsUp("Shirley") // Returns: "What's up Shirley?"

Because closures are stored in variables, you can pass them into (and out of) functions just like any other type:

1
2
3
4
5
6
7
8
9
10
11
12
// This function accepts a String, and a closure
// that itself takes a String and returns a String
func greet(_ name: String,
          with greeting: (String) -> String) {
    let phrase = greeting(name)
    print(phrase)
}

// That definition matches our sayWhatsUp closure,
// so we can pass it.
greet("Jeff", with: sayWhatsUp)
// Prints: "What's up Jeff?"

If you have a function that takes a closure as its last argument, you can define it after the closing parenthesis of the function call. This is called a trailing closure:

1
2
3
4
greet("Pierce") { name in
    return "Oh... Hello \(name)."
}
// Prints: "Oh... Hello Pierce."

Reflections

I guess closures are hard to grasp for some people. I don’t feel like I ever really struggled with them, but Swift was basically the first language I learned, so I may have just forgotten struggling with them. I do remember wondering why they were interesting though, when at first it just seems like a slightly different way to define functions. But then things clicked for me when I first used .map and .filter, functions where you pass a closure to customize how they work. And since then, I continue to find more places where closures are very useful, like when you want to run a block of code after some background task has finished.