Weekly Swift articles, podcasts and tips by John Sundell.

Implementing throwing protocol functions as non-throwing

Published on 05 Nov 2019

In Swift, it’s possible to satisfy a throwing function protocol requirement using a non-throwing function, which can be very useful in certain situations. For example, let’s say that we’ve defined a protocol for parsers that enable us tokenize a string in some way:

protocol TokenParser {
    func parseToken(from string: String) throws -> Token
}

While certain implementations of the above protocol will need to throw, that won’t necessarily be true for all conforming types. For example, the below KeywordParser throws, while TextParser doesn’t:

struct KeywordParser: TokenParser {
    func parseToken(from string: String) throws -> Token {
        ...
    }
}

struct TextParser: TokenParser {
    // This will satisfy our protocol requirement, even though
    // this implementation doesn't actually throw:
    func parseToken(from string: String) -> Token {
        ...
    }
}

Since the original declaration of our protocol function is marked as throwing, we’ll always need to call it with try when the exact conforming type isn’t known — regardless of whether the underlying implementation actually throws:

let parsers: [TokenParser] = ...

for parser in parsers {
    // Since all we know about each parser within this iteration
    // is that it conforms to our 'TokenParser' protocol, we'll
    // need to use 'try' when calling its function:
    let token = try parser.parseToken(from: string)
}

However, when dealing with a non-throwing conforming type directly, we can now omit the try keyword — even though the original protocol requirement was marked as throwing:

let parser = TextParser()
let text = parser.parseToken(from: string)

It’s a small feature, but the fact that we can implement a throwing function requirement using a non-throwing one gives us a slightly greater degree of flexibility when conforming to protocols that contain such functions.