Experiment: Lazy Objects in Swift
Tags: swift, programming
Published: 2018-03-16 10:55:16

---
title: Experiment: Lazy Objects in Swift
published: true
description: 
tags: swift,programming
---

> NEW: This blog post is also available on my [personal website](https://floschliep.com/blog/2018-03-15-experiment-lazy-objects-in-swift) alongside even more content!

*Disclaimer: This post is purely experimental based on an idea I had recently, I’m personally not using this in production right now.*

Laziness in Swift can be a very powerful tool, but it hasn’t reached its full potential yet. Recently, I came across a situation where I *wanted* to write something likes this:
{% gist https://gist.github.com/floschliep/1d5e902851a8e5f9c05b1b00fcff78f1 %}

In other words: I wanted to pass the closure for creating a lazy property to the initializer of my class *and* make it a constant property. This doesn’t work because of two reasons:

- Properties are being evaluated upon instantiation of the object, except for lazy variables. `lazy let` doesn’t exist in Swift.
- Lazy properties must declare their initializer, meaning you can’t pass a closure as the initializer to it.

With those constraints, our only option is to use existing features to make this work. Here’s what I expect from my implementation:

- Pass a closure, which won’t be evaluated until it’s necessary, to *something*.
- The closure should only be *evaluated once*, otherwise this would defeat the purpose of the whole concept as we could just use a normal closure.
- This should be universally usable with *anything*.
- A readable, easy-to-understand syntax.

No 3 will be easy to satisfy by using Generics. Due to No 1 & 2 it will be necessary to use a `class`, as evaluating and storing the result of our closure implicitly mutates the object.
{% gist https://gist.github.com/floschliep/735ff6bdb232fd7922eb3582b986ca4b %}

Using our `LazyObject` wrapper now looks like this:
{% gist https://gist.github.com/floschliep/884fe3063754665647923b8e4b1aee3a %}

Only on the last line the closure will actually be evaluated and our `Bar` object created. Calling `bar.object` again would just return the cached object and not evaluate the closure again.

So far so good. What about structs though? Right now, our wrapper doesn’t allow mutating the underlying `object`. Let’s create a mutable subclass, `MutableLazyObject`, that provides a scope allowing mutation:
{% gist https://gist.github.com/floschliep/6c109782a21b91d15c98d74d706654eb %}

By moving the `use(_:)` method to a subclass, we can explicitly decide whether we want to allow mutation or not.
{% gist https://gist.github.com/floschliep/df08b15df929df929561ca606445ca1b %}

Unfortunately though, using the `LazyObject` class doesn’t look nice, violating expectation No 4. Let’s write a short helper function:
{% gist https://gist.github.com/floschliep/5e9fccd9920110e28bcb9436524d1566 %}

This function allows us to use the shorthand syntax `lazy(Bar())`. Much better!

___

The full code, including tests, is available on [GitHub](https://github.com/floschliep/LazyObject). I’d love to get some feedback on this! Is this a good idea? Why or why not? Should Swift allow this kind of functionality on the language level?