Lazy Variables in Swift with Examples: Complete Guide

In Swift, a lazy variable is a variable that gets initialized only when it is called for the first time.

.
.
.
    lazy var BMIIndex: Double = {
        return weight / pow(height, 2)
    }()
.
.
.

To put it another way, using a lazy variable, you can delay the initialization of stored property.

This is a great feature due to the limitations in the computing power.

A lazy variable does not spend excess memory before it is called for the first time. If the variable is never called, it is not going to be initialized.

This saves you resources on initializing computationally heavy variables.

In this guide, you learn:

  • What is a lazy variable in Swift
  • How to use a lazy variable
  • What is the difference to a computed property

Lazy Vars in Swift

A lazy variable is a stored property that gets initialized on demand.

You only can have lazy variables inside a struct or a class.

For instance, let’s create a Person structure with a lazy variable for calculating the BMI index:

struct Person {
    var weight: Double
    var height: Double

    lazy var BMIIndex: Double = {
        return weight / pow(height, 2)
    }()
}

When you initialize a Person object the BMI index is not calculated automatically. Instead, it is calculated when you first try to access it.

var jack = Person(weight: 90, height: 1.92)
print(jack.BMIIndex)

Output:

24.4140625

Let’s dig deeper into the details of declaring a lazy variable.

The Anatomy of a Lazy Var in Swift

In the above illustration, you can see the key characteristics of a lazy variable.

If any one of these characteristics is missing, the code fails to run.

Let’s have a closer look at the anatomy of a lazy variable:

  • A lazy variable belongs to a class or a structure. You cannot declare a lazy variable anywhere in the code.
  • To make a variable lazy, use the keyword modifier lazy in front of var.
  • Instead of directly assigning a value to the lazy variable, it has to be computed.
    • The computation takes place in a block of code.
    • Use curly braces to define the block of code.
    • Return a value from the block of code. It is then assigned to the lazy variable.
    • Assign the block of code to the lazy variable.
  • Add the parenthesis () after the curly braces.

Now you understand how to initialize a lazy variable in your Swift program.

Next, let’s compare lazy variables to a closely related feature called computed property.

Lazy Var vs Computed Property

At this point, you may wonder why would we use a lazy variable instead of a computed property.

If you do not know what a computed property is, it is a property that is computed on demand.

In other words, the value is calculated when you call it.

Let’s modify the above example that uses a lazy variable to use a computed property instead:

struct Person {
    var weight: Double
    var height: Double

    var BMIIndex: Double {
        get {
            return self.weight / pow(self.height, 2)
        }
    }
}

var jack = Person(weight: 90, height: 1.92)
print(jack.BMIIndex)

Output:

24.4140625

As you can see, this piece of code produces the same output as the previous example.

The behavior seems to be very similar to lazy variables.

But what is the difference between a lazy variable and a computed property?

  • A lazy variable is a stored property whose initialization is delayed. The initial value is computed only one time.
  • A computed property is a value that is not stored anywhere. Instead, it is always computed on demand.

But which one should you use?

It depends on the context.

If you want a stored property that does not get initialized before needed, use a lazy variable.

If you need a property that does not store a value but always calculates it, use a computed property.

To make more sense of this, let’s see a couple of examples.

Example 1.

Let’s see how a lazy variable causes problems and how a computed property saves the day.

Let’s jump back to the previous example where we demonstrate using lazy variables to compute the BMI index of a person:

struct Person {
    var weight: Double
    var height: Double

    lazy var BMIIndex: Double = {
        return weight / pow(height, 2)
    }()
}

Let’s create a Person object and print his BMI index:

var jack = Person(weight: 90, height: 1.92)
print(jack.BMIIndex)

Output:

24.4140625

Then, let’s change the weight and print the BMI index again.

When the weight changes, the BMI index should change as well:

jack.weight = 130
print(jack.BMIIndex)

Output:

24.4140625

As you can see, the BMI index did not change.

The lazy variable only computes the BMI index once and stores it to the variable. So unless we manually change it, it will always remain the same.

This is actually a great example of a situation where you should use a computed property.

struct Person {
    var weight: Double
    var height: Double

    var BMIIndex: Double {
        get {
            return self.weight / pow(self.height, 2)
        }
    }
}

var jack = Person(weight: 90, height: 1.92)
print(jack.BMIIndex) // prints 24.4140625

// Change the weight
jack.weight = 130
print(jack.BMIIndex) // prints 35.26475694444444

As you can see, now the BMI index is always correct whether you change the weight/height or not.

The original example demonstrates how to use lazy variables in Swift.

However, in this case, it makes sense to use a computed property instead.

Next, let’s see another a bit more abstract example that demonstrates how using a lazy variable outperforms using a computed property.

Example 2.

As another example, let’s compare the performance between a lazy variable and a computed property.

This piece of code represents a math operation whose value takes 2 seconds to compute. Furthermore, we access the result 5 times in a for loop.

First, let’s use a lazy variable:

struct Operation {
    lazy var result: Double = {
        // Simulates a task that takes 2 seconds to calculate
        sleep(2)
        return 10
    }()
}

var op = Operation()

for _ in 1...5 {
    print(op.result)
}

2 seconds later, this piece of code prints out:

10.0
10.0
10.0
10.0
10.0

Now, if we used a computed property instead, it takes way longer to print the values.

This is because, during each iteration of the loop, the computed property performs the calculation that takes time.

struct Operation {
    var result: Double {
        get {
            // Simulates a task that takes 2 seconds to calculate
            sleep(2)
            return 10
        }
    }
}

var op = Operation()

for _ in 1...5 {
    print(op.result)
}

Now it takes 5 x 2 = 10 seconds to print the result:

10.0
10.0
10.0
10.0
10.0

(Please run these pieces of code in your playground to get a better picture of the performance.)

Anyway, this demonstrates how using a lazy variable can be more efficient than using a computed property.

Last but not least, let’s go through the basic limitations of using lazy variables in Swift.

Limitations on Lazy Variables

As you have already seen, there is a couple of limitations when it comes to using lazy variables in Swift.

Here is a complete list of all the limitations:

  • Lazy variables are only allowed inside structures or classes.
  • You cannot declare a lazy constant (lazy let) because then its value could not change.
  • A computed property cannot be a lazy variable. This is because a computed property is always recalculated when it is called.
  • The initialization of a lazy variable is not an atomic operation. Thus, lazy variables are not thread safe.

Conclusion

Today you learned what is a lazy variable in Swift.

To recap, a lazy variable lets you delay the initialization of stored property.

This can save some resources, especially if the calculation is big.

If the variable is not needed, it is not going to be computed.

The difference between a lazy variable and a computed property is that a computed property computes the value always. The lazy variable only computes the value once.

Thanks for reading.

Happy coding!

Scroll to Top