Hidden feature: subscript


You’re more of a video kind of person? I’ve got you covered! Here’s a video with the same content than this article 🍿


There’s a good chance that you’ve already used subscripts at one point or another.

But did you know that they have a hidden feature?

Let’s start with a quick recap on how a subscript works!

A subscript is actually very similar to a method!

The two main differences are that you declare it by using the keyword subscript instead of func and that it doesn’t have a name:

This absence of a name is on purpose, because subscripts are called with a special syntax that uses square brackets:

Most of the time, we use simple subscripts that take only a single argument.

But it’s actually possible to define more complex subscripts!

For instance, Dictionary comes with a subscript that allows you to provide a defaultValue that will be returned if the Dictionary doesn’t contain the given key.

Even better, you can also define an overload of an existing subscript, but with a different external name for the argument.

We can use this approach to define this alternate subscript on Collection, which takes an index of the Collection just like the regular subscript already does, but this time with an added external argument name.

And then we can call this alternate subscript instead of the regular one by using the external argument name:

That’s all for this article, I hope you’ve enjoyed learning this new trick!

Here’s the code if you want to experiment with it:

extension Array {
    subscript(index: Int) -> Element {
        // ...
    }
}

let numbers = [0, 2, 4]

numbers[2] // returns 4

extension Dictionary {
    subscript(
        key: Key,
        default defaultValue: @autoclosure () -> Value
    ) -> Value {
        // ...
    }
}

let dictionary = [ "zero": 0, "one": 1, "two": 2]

dictionary["two", default: -1] // returns 2
dictionary["three", default: -1] // returns -1

extension Collection {
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

let data = [1, 3, 4]

data[10] // will crash 💥
data[safe: 10] // returns nil
Previous
Previous

Bad practice: loading a large image on the main thread

Next
Next

How to write Unit Tests for Code Performance ⏱️