Blog / April 16, 2021 / 5 mins read / By Suneet Agrawal

if vs if let vs guard let in Swift

if let and guard let are two conditional operators or condition checker which make our life super easy. Other languages have only if as condition checker but swift provides if let as well as guard let also which are operationally same but a bit different in functionality.

To understand their differences, let’s try to understand what they are in details first.

if condition

Normal if condition is nothing but to check whether a condition is true or not.

let colors = ["red", "green", "blue"]

if colors.contains("red") {
  print("red is present in palette")
}

This can be clubbed with else and else if but both of them are optional.

let colors = ["red", "green", "blue"]
 
if colors.contains("red") {
  print("red is present in palette")
} else {
  print("red is not present in palette")
}

we can even club multiple if conditions with simple && or || operators based on the use case.

let colors = ["red", "green", "blue"]

if colors.contains("red") || colors.contains("green") {
  print("red or green are present in palette")
} else {
  print("red and green both are not present in palette")
}

if let

Now let’s think about someplace where we want to compute something and based on the computed value we need to put an if condition.

let colors = ["red", "green", "blue"]

let index = colors.firstIndex(where: {$0.elementsEqual("green")})

if index != nil {
  print("green is present in palette at position \(index ?? -1)")
} else {
  print("green is not present in palette")
}

We are trying to check if an element is present in an array and if present we are trying to print its position.

The same code can be replaced with if let instead of if condition.

let colors = ["red", "green", "blue"]

if let index = colors.firstIndex(where: {$0.elementsEqual("green")}) {
  print("green is present in palette at position \(index)")
} else {
  print("green is not present in palette")
}

We combined the computation and evaluation within a single statement by using if let.

The thing to notice here is that the variable index is not nullable in if let whereas it was a nullable variable in if condition.

We can club multiple if let also within the same condition check by spearating them using comma ,

let colors : [String] = ["red", "green", "blue"]

if let redIndex = colors.firstIndex(where: {$0.elementsEqual("red")}),
  let greenIndex = colors.firstIndex(where: {$0.elementsEqual("green")}) {
      print("red is present in palette at position \(redIndex) and green is present in palette at position \(greenIndex)")
} else {
      print("\(red) and \(green) are not present in palette")
}

Or we can even check the nullability and assign it to another variable that will be non-nullable. This is called optional unwrapping.

let colors : [String]? = ["red", "green", "blue"]
let nullableGreen : String? = "green"

if let green = nullableGreen,
  let index = colors?.firstIndex(where: {$0.elementsEqual(green)}) {
    print("\(green) is present in palette at position \(index)")
} else {
    print("\(nullableGreen ?? "undefined") is not present in palette")
}
The thing to notice here is that the variable green is only accessible only in if let but not in the else scope. It’s not event available after the if else scope.
let colors : [String]? = ["red", "green", "blue"]
let nullableGreen : String? = "green"

if let green = nullableGreen,
   let index = colors?.firstIndex(where: {$0.elementsEqual(green)}) {
      print("\(green) is present in palette at position \(index)")
} else {
      print("\(nullableGreen ?? "undefined") is not present in palette")
}

print(green) <e>//Compile type error: cannot find 'green' in scope</e>

guard let

guard let can also be used for condition check and it can also unwrap the optional values but it works a bit different from if let.

guard let is designed to exit the current function, loop, or condition if the check fails.

func checkColorInPalette() {
  let colors : [String] = ["red", "green", "blue"]

  guard let index = colors.firstIndex(where: {$0.elementsEqual("green")}) else {
    print("green is not present in palette")
    return
  }

  print(print("green is present in palette at position \(index)"))
}

Similar to if let, guard let can also be clubbed with multiple let conditions using comma , and it can also be used for optional unwrapping.

func checkColorInPalette() {
    let colors : [String] = ["red", "green", "blue"]
    let nullableGreen : String? = "green"

    guard let green = nullableGreen,
          let index = colors.firstIndex(where: {$0.elementsEqual(green)}) else {
            print("green is not present in palette")
            return
    }

    print(print("\(green) is present in palette at position \(index)"))
}

The important thing to notice here is that the let variables defined in guard statements are also accessible after the statement but they are inaccessible inside the else condition.

Difference between if and if let/guard let

  • if is just a conditional checker whereas if let and guard let can define variables also where we can do computation.
  • We can club multiple conditions or expression in all three.
  • Only if let or guard let can do the optional unwrapping.

Difference between if let and guard let

  • if let is similar to if condition with the additional functionality of defining let variable where we can do the computation or optional unwrapping.
  • guard let is also similar to if let but it focus on the “happy path” means if the condition is not true, code will not execute further in that particular function, loop or condition but it will return, break or throw.
  • In if let, the defined let variables are available within the scope of that if condition but not in else condition or even below that.

In guard let, the defined let variables are not available in the else condition but after that, it’s available throughout till the function ends or anything.

Comments