Learn

Closures are first-class citizens in Swift. This means they can be assigned to variables and passed as arguments to functions. Now that we’ve looked at assigning them to variables, let’s see how we can pass them to functions.

A function that accepts a closure as an argument is known as a higher-order function. This pattern is very common in Swift, and we will take a closer look at some built-in higher-order functions in a later exercise.

For now though, the science division is so excited about the transformation closure that they assigned us another task! They would like us to create a function that takes a closure that describes a Teenage Mutant Ninja Turtle. We’re not quite sure what they’re cooking over there but it sounds pretty wild!

Let’s start by defining a closure that takes a String as input and prints the turtle’s ability to the console:

let turtleAbility: (String) -> Void = { turtle in switch turtle { case "Leonardo": print("Jujitsu") case "Raphael": print("Super strength") case "Donatello": print("Intelligence") case "Michelangelo": print("Eating pizza") default: print("Unknown TNMT") } }

The closure definition should look familiar from the previous exercise. We name the closure turtleAbility which takes a String as an input and returns Void. Within the braces, we name the String parameter turtle. In the body of the closure, we switch on turtle and print its ability.

Next, lets define a function that takes a String and closure as a parameter:

func description(for turtle: String, descriptionClosure: (String) -> Void) { descriptionClosure(turtle) }

We have a function named description(for:descriptionClosure) that takes a String as an input, named turtle and a closure named descriptionClosure. The closure type matches that of the turtleAbility we defined earlier. See where this is going? Just like with functions, if they type matches, we can pass it as an argument. Here’s what the calling code looks like:

description(for: "Michelangelo", descriptionClosure: turtleAbility) // prints “Eating pizza”

What’s cool about this is we can define an entirely new closure with the same type and pass it to the description function to get different functionality. Consider the following closure which print’s the turtle’s color:

let turtleColor: (String) -> Void = { turtle in switch turtle { case "Leonardo": print("Blue") case "Raphael": print("Red") case "Donatello": print("Purple") case "Michelangelo": print("Orange") default: print("Unknown TNMT") } }

And when we call the description function with the turtleColor closure:

description(for: "Donatello", descriptionClosure: turtleColor) // prints “Purple”

Awesome. Now we can pass closures to functions like it’s our own super ability!

Instructions

1.

To start, create a function named handValue that takes an array of integers named cards and a closure named scoringRules of type (Int) -> Int named value. The function should return an integer which will be the value of the hand.

2.

In the body of the handValue function, calculate the value of the hand with the scoring rules closure and return the value. Start by adding a variable named totalValue initialized to 0. Then apply the closure to each card by looping through the cards array. Return totalValue.

3.

Define a closure named allCards that matches the scoringRules type in our handValue function that counts all cards. Call the handValue function with the allCards closure. What do you expect the output to be?

4.

Define a closure named onlyEvens that matches the scoringRules type in our handValue function. The closure should only count cards if they are even. Use the isMultiple(of:) function to determine if the card is even. Call the handValue function with the closure. What do you expect the output to be?

Take this course for free

By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.
Already have an account?