Programming in Swift: Functions & Types

Jan 4 2022 · Swift 5.5, iOS 15, Xcode 13

Part 3: Enumerations

25. Challenge: Switch Statements

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 24. More Switch Statements Next episode: 26. Associated Values

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 25. Challenge: Switch Statements

Update Notes: This course was originally recorded in 2019. It has been reviewed and all content and materials updated as of October 2021.

Transcript: 25. Challenge: Switch Statements

Your next challenge is here! This time you’ll be testing yourself on switch statements. You’ll find everything you need on page 6 of the Playground for this part of the course. Pause the video, give it your best try, and then come back to check my solution.

For the first challenge, I’ll start out by declaring a String constant, to hold a life stage.

let lifeStage: String

Then I’ll switch on a tuple of a name and age.

switch ("Ozma", 7) {

}

Now I can make a case for the first life stage, bind the first tuple value to “name”, and use a range for the second value.

case (let name, 0...2):

and then in the body of the case, set that lifeStage constant to say that someone between 0 and 2 is an infant.

case (let name, 0...2):
  😺lifeStage = "\(name) is Infant."

There are 5 more cases to make, but this first one is a good starting place, so I’ll copy and paste it 5 times.

And now I can just update the ranges and strings for each case. 3 to 12 is a child…

case (let name, 3...12):
  lifeStage = "\(name) is Child."

13 to 19 is a teenager…

case (let name, 13...19):
  lifeStage = "\(name) is Teenager."

Someone 20 to 39 is an adult.

case (let name, 20...39):
  lifeStageForName = "\(name) is Adult."

40 to 60 is middle aged…

case (let name, 40...60):
  lifeStage = "\(name) is Middle aged."

and over 60 is elderly.

case (let name, 61...):
  lifeStage = "\(name) is Eldery."

I took advantage of the open-ended triple-dot syntax for the “Elderly” case. Anything greater than 61? It would be caught there, so the default would only catch negative numbers. It also might be invalid for someone to live to be over nine quintillion, which the range of Int goes up to, but I decided not to get morbid. You can check for a more realistic range if you like!

Then, to make this switch statement exhaustive, I’ll ignore the name, and say any age not covered by previous cases is unaccounted for.

case (_, let age):
  lifeStage = "Unaccounted for age: \(age)."

Run the playground and if Ozma were a human person, she’d be a child.

The second challenge was a little more involved! I need to start with the Direction enumeration, and a case for each direction.

enum Direction {
  case north, south, east, west
}

And then a function that will take in a Direction array…

func getLocation(for movements: [Direction])

and return a tuple that represents a location. I’ll go ahead and name the values “x” and “y” like you might for a 2D coordinate.

func getLocation(for movements: [Direction])😺 -> (x: Int, y: Int) {

}

I’ll set up a variable to hold the location, and start it at 0, 0

  var location = (x: 0, y: 0)

And then I need to adjust that location based on each movement, in order. There’s different ways you might have done this! I’ll show you two possible solutions. First, I’ll use a for loop to loop through the movements…

for movement in movements {

}

and inside of that loop, switch on each movement.

    switch movement {

Then update the location differently for each case. So if there’s a move north, add 1 to the y value.

    case .north:
      location.y += 1

Do the opposite for a move south

    case .south:
      location.y -= 1

For a move east, add one to the x value.

    case .east:
      location.x += 1

and then do the opposite for west.

    case .west:
      location.x -= 1

After all of that, location should represent the final location of our character, so I’ll return that value.

  return location

Now I can try calling the function and passing in the example directions…

getLocation(for: [.north, .west, .west])

and run the playground to see if I get that expected result of (-2, 1). I do! So, that’s one way to do it.

The other way I tried was to replace this for loop with reduce(into). I’ll get rid of this location variable…

❌  var location = (x: 0, y: 0)❌

and replace this first line of the for loop, instead calling reduce(into) on the movements array.

movements.reduce(into: 

The starting tuple I want is 0, 0.

movements.reduce(into: 😺(x: 0, y: 0))🛑 

And in the closure, I’ll name the parameters location and movement.

movements.reduce(into: (x: 0, y: 0)) 😺{ (location, movement) in 🛑

Because I named the elements in the tuple, and these parameters to match the code I already had, I can just keep this switch statement exactly as it is! Just make sure it’s wrapped in the closure body.

...
  case .west:
    location.x -= 1
  }
😺}🛑

Now I can delete this return statement.

  ❌return location❌

Because the result of all of this code will be implicitly returned for me! To prove that, when I run the playground again… I get the same result!