Swift 5’s Lazy Keyword Explained

How to run your classes’ code when you’re ready for it

Alec Mather
Better Programming

--

Prerequisites to understand:

  • Swift 5 syntax

You may have seen someone else’s Swift code include the keyword lazy, but what does that mean? The lazy keyword is used to solve problems with processing speed.

Let’s say we have a struct:

struct Person {  var age: Int = 16}

Now, this is a pretty simple struct. And if we want to access the age property of a Person instance, it will be lightning fast. I mean…all we’re doing is returning a value.

So, let’s do that:

let person: Person = Person()
print(person.age)

No problems here…

Now, what if, somehow, we had a property in this struct that was extremely difficult to compute? What if it took six seconds just to compute that property?

Let’s take a look into what’s actually happening when we instantiate our instance.

When we assign the person variable to a new Person(), the values for the properties are calculated and assigned. Then, when we want to access them, they are retrieved from their place in memory.

Let’s introduce the problem using the common Fibonacci algorithm, an algorithm that is known to introduce “time to compute” problems.

We now have a property on our Person struct that could cause us some problems.

And here’s the problem: Every time a class is instantiated, the properties are computed to produce the instance.

This means that every time we just want to go like this:

let person: Person = Person()

Our code is going to be calculating the fibonacciOfAge property.

And because this recursive algorithm could potentially cause a little bit of lag on that initiation, we basically want to tell our class the following: “Hey, don’t compute that fibonacciOfAge property when you’re initiated, only compute it if I ask you for it.”

This is what we use the lazy keyword for. Let’s fix our problem:

By adding lazy to that property, we are telling our struct not to compute that property unless we specifically need it.

This is what’s going to happen:

let person: Person = Person() // fibonacciOfAge NOT computed
print(person.fibonacciOfAge) // fibonacciOfAge IS computed

This is a powerful tool. Say we want to populate a game with one billion people, who all have the fibonacciOfAge property. When we start the game, we don’t want to spend a ton of time computing all of their fibonacciOfAge properties.

We just want to instantiate all the people, and only compute one individual’s fibonacciOfAge on a case by case basis.

Now, you may be asking the question: “Why isn’t everything a lazy variable then?”

The reason we don’t allocate everything as a lazy variable is because we still want lightning-fast response times for simple variables.

If every time we ever wanted to access a property, we had to compute it, our game would run much slower.

Hope this was helpful to some people!

Happy coding.

Cheers.

--

--