---
title: "Top 7 Subtle Swift Features"
slug: "top-7-subtle-swift-features"
date: "2022-04-09T10:41:05.000Z"
description: "Here, I collected Swift features that are less known and can be useful when you prepare for interviews or want to deepen your Swift knowledge."
---

# Top 7 Subtle Swift Features

## 1\. Keyword `indirect`

It’s used with enums only. As you know, enums are **value type** and stored on the stack. Therefore, the compiler needs to know how much memory each enum takes. As only one option is possible at any moment, the enum occupies the memory of the largest case plus some operational information.

```swift
// Just a general enum, nothing fancy
enum Foo {
    case bizz(String)
    case fizz(Int)
}
```

But what if we make enum dependant on itself?

```swift
// Infinite size??
enum Foo {
    case bizz(Foo)
    case fizz
}
```

This definition generates a compiler error.

😡

Recursive enum `Foo` is not marked `indirect`

The error makes sense: the compiler can’t calculate `Foo` size as it tends to infinity. Here comes the `indirect` keyword.

```swift
// Oh, fine
enum Foo {
    indirect case bizz(Foo)
    case fizz
}
```

**Simple:** it modifies the enum memory structure to solve the recursion problem. **Detailed:** `.bizz(Foo)` is no longer stored inline in memory. Actually, with the `indirect` modifier data is now stored behind a pointer (indirectly).

Problem solved! Also, we can modify the whole enum as indirect

```swift
// Every case is indirect now
indirect enum Foo {
    case bizz(Foo?)
    case fizz(Foo?)
}
```

* * *

## 2\. Attribute `@autoclosure`

Swift’s `@autoclosure` attribute enables you to define an argument that automatically gets wrapped in a closure. It’s mostly used to defer the execution of an expression to when it’s actually needed.

```swift
func calculate(_ expression: @autoclosure () -> Int,
               zero: Bool) -> Int {
    guard !zero else {
        return 0
    }

    return expression()
}
```

Then, calculate can be called like this:

```swift
calculate(1 + 2, zero: false) // 3

calculate([Int](repeating: 5, count: 10000000).reduce(0, +),
                zero: false) // 50000000

calculate([Int](repeating: 5, count: 1000).reduce(0, +),
                zero: true) // 0
```

So, in this case, when `zero: true`, the call of `calculate` does not calculate the expression at all, improving code performance.

[Subscribe and don't miss posts!](https://alexdremov.me/#/portal/signup)

* * *

## 3\. Lazy

A `lazy` stored property is a property whose initial value isn’t calculated until the first time it’s used. Lazy properties must always be declared as a variable. Note that if you use `lazy` in `struct`, then the function that uses it must be marked as `mutating`.

```swift
class Foo {
    lazy var bonk = DBConnection()
    
    func send() {
        bonk.sendMessage()
    }
}
```

We already covered `@autoclosure` which also can help to defer expression evaluation. That can be used with `lazy`! Consider this common case of dependency injection.

```swift
class Foo {
    let bonkProvider: () -> DBConnection
    lazy var bonk: DBConnection = bonkProvider()
    
    init(_ expression: @escaping @autoclosure () -> DBConnection) {
        self.bonkProvider = expression
    }
    
    func send() {
    	// Here bonkProvider() is called
        // only for the first call of send()
        bonk.sendMessage()
    }
}
```

* * *

## 4\. Enums as namespaces

Swift does not have namespaces, which may be a problem in big projects. This is easily solved with enums.

```swift
enum API {}

extension API {
    static let token = "…"

    struct CatsCounter {
        …
    }
}

let a = API.CatsCounter()
print(API.token)
```

* * *

## 5\. Dynamic member lookup

This section describes the `@dynamicMemberLookup` attribute. It can be used with structs and classes.

Just adding `@dynamicMemberLookup` to the definition generates an error

😡

`@dynamicMemberLookup` attribute requires `Foo` to have a `subscript(dynamicMember:)` method that accepts either `ExpressibleByStringLiteral` or a `key path`

Therefore, such subscript needs to be defined

```swift
@dynamicMemberLookup
class Foo {
    subscript(dynamicMember string: String) -> String {
        return string
    }
}

let a = Foo()
print(a.helloWorld)
```

In `subscript` you can implement much more complex logic to retrieve data. But you can see how this implementation is limited to strings only and not really safe. This can be modified with a `key path`.

```swift
class Bob {
    let age = 22
    let name = "Bob"
}

@dynamicMemberLookup
class Foo {
    let himself = Bob()
    
    subscript<T>(dynamicMember keyPath: KeyPath<Bob, T>) -> T {
        return himself[keyPath: keyPath]
    }
}

let a = Foo()
print(a.age)
```

Even though you know about this feature does not mean that it should be used everywhere. It’s up to you what is more readable and expressive: `a.himself.age` or `a.age`.

* * *

## 6\. Dynamically callable

Also, a compiler feature that allows you to call objects. Can be applied to `struct`, `enum`, and `class`.

After adding the attribute, the error is generated:

😡

`@dynamicCallable` attribute requires `RangeGenerator` to have either a valid `dynamicallyCall(withArguments:)` method or `dynamicallyCall(withKeywordArguments:)` method

The method signature is similar to that of `@dynamicMemberLookup`.

```swift
@dynamicCallable
struct RangeGenerator {
    var range: Range<Int>
    
    func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> [Int] {
        if args.count > 1 || args.first?.key != "count" {
            fatalError("Unknown arguments \(args)")
        }
        let count = args.first!.value
        return (0..<count).map{ _ in Int.random(in: range) }
    }
}

let gen = RangeGenerator(range: 0..<100)
print(gen(count: 13))
// [2, 89, 4, 17, 65, 26, 73, 86, 93, 13, 25, 96, 96]
```

* * *

## 7\. Inlining

Sometimes you want to give additional information about optimisations the compiler can use. Inlining code is one of the most important optimization features. So, how to use `‌@inlinable`, `@inline(__always)`, `@usableFromInline`?

The `@inlinable` attribute exports the body of a function as part of a module's interface, making it available to the optimizer when referenced from other modules.

As a result, `@inlinable` makes the implementation of the method public and able to be inlined into the caller. Secondly, it forces you to make everything it calls `@usableFromInline`.

`@inline(__always)` tells the compiler to ignore inlining heuristics and always (almost) inline the function.

A function that is `@inline(__always)`, but not `@inlinable`, will not be available for inlining outside its module, because the function's code is not available.

💥

`@inline(__always)` can be beneficial for performance, but it can also have catastrophic effects on macro performance due to code size increase.

```swift
struct Foo {
    @inlinable
    @inline(__always)
    func simpleComputation(_ a: Int, _ b: Int) -> Int {
        duplicate(a) + duplicate(b)
    }
    
    @usableFromInline
    func duplicate(_ c: Int) -> Int {
        c * 2
    }
    
    func general() {
        print("Hello world")
    }
}
```

This has more effects on implementation, check the discussion on this [forum](https://forums.swift.org/t/when-should-both-inlinable-and-inline-always-be-used/37375) if you want to understand this in-depth

## References

1.  [https://www.swiftbysundell.com/articles/using-autoclosure-when-designing-swift-apis/](https://www.swiftbysundell.com/articles/using-autoclosure-when-designing-swift-apis/)
2.  [https://www.swiftbysundell.com/articles/powerful-ways-to-use-swift-enums/](https://www.swiftbysundell.com/articles/powerful-ways-to-use-swift-enums/)
3.  [https://www.hackingwithswift.com/articles/134/how-to-use-dynamiccallable-in-swift](https://www.hackingwithswift.com/articles/134/how-to-use-dynamiccallable-in-swift)
4.  [https://www.hackingwithswift.com/example-code/language/what-are-lazy-variables](https://www.hackingwithswift.com/example-code/language/what-are-lazy-variables)
5.  [https://forums.swift.org/t/who-benefits-from-the-indirect-keyword/20167](https://forums.swift.org/t/who-benefits-from-the-indirect-keyword/20167)
6.  [https://www.tothenew.com/blog/recursive-enumerations-in-swift/](https://www.tothenew.com/blog/recursive-enumerations-in-swift/)
7.  [https://www.avanderlee.com/swift/dynamic-member-lookup/](https://www.avanderlee.com/swift/dynamic-member-lookup/)