Cleaner inits - ExpressibleBy... protocols

Photo by Aaditya Ailawadhi / Unsplash

Sometimes structures or classes we create in code can be easily expressed by built-in Swift types. Consider the following code:

struct Person {
    let name: String
}

let ana = Person(name: "Ana")

I created simple Person a struct that holds a person's name. To create this structure we need to explicitly call its auto-generated constructor.

There is a better way, Swift provides a couple of protocols that can make initialization nicer and simpler. In our case, we need ExpressibleByStringLiteral. Swift requires to implement custom init(stringLiteral value: Self.StringLiteralType). We are using String.
Let's refactor our code:

struct Person: ExpressibleByStringLiteral {
    init(stringLiteral value: String) {
        name = value
    }
    let name: String
}

let ana: Person = "Ana"

Now instead of calling initializer directly, we can make Swift call it for us - I'm creating Person by assigning String. Swift will create Person for us because we used ExpressibleByStringLiteral.

We can use the power of expressible protocols with generics and extensions. I'll create a generic stack in Swift:

struct Stack<T> {
    private var array = [T]()
    
    func peek() -> T? {
        array.last
    }
    
    mutating func pop() -> T? {
        array.popLast()
    }
    
    mutating func push(_ element: T) {
        array.append(element)
    }
}

Now, I want to be able to create a stack from an array. To do this we need to add a new initializer:

extension Stack {
    init(from array: [T]) {
        array.forEach {
            push($0)
        }
    }
}
var stack = Stack(from: [1, 2, 3, 4])
stack.pop() // gives 4

Well... I don't like it! I can improve it by using the power of ExpressibleByArrayLiteral and extensions:

extension Stack: ExpressibleByArrayLiteral {
    init(arrayLiteral elements: T...) {
        self.init(from: elements)
    }
}

var stack: Stack = [1, 2, 3, 4]

And you don't even have to specify the type of stack in <>! Swift will figure it all by itself!

Swift standard library provides protocols for a couple of built-in types - more information can be found here.

If you like my posts, check out my Twitter!

Artur Gruchała

Artur Gruchała

I started learning iOS development when Swift was introduced. Since then I've tried Xamarin, Flutter, and React Native. Nothing is better than native code:)
Poland