Weekly Swift articles, podcasts and tips by John Sundell.

Referring to overloaded functions

Published on 19 Aug 2019

Here’s a nice little trick that enables an overloaded function/initializer to be passed as an argument. Normally, attempting to do so results in an error, since the compiler can’t know which overload we’re referring to. Thankfully, we can use parameter labels to disambiguate.

// Here File has two initializers that both have the
// same shape: (String) -> File:
struct File {
    init(name: String) {
        ...
    }

    init(path: String) {
        ...
    }
}

func render(_ markdown: Markdown,
            usingTemplateNamed name: String? = nil) {
    // Normally we can pass initializers as functions, but in
    // this case we'll get an error, since the compiler can't
    // know which of the two initializers that we're referring
    // to (since they both accept a String).
    let template = name.map(File.init)
    ...
}

func render(_ markdown: Markdown,
            usingTemplateNamed name: String? = nil) {
    // Solution: We'll include the parameter label for
    // the initializer we're referring to when passing
    // it, to disambiguate between the two candidates.
    let template = name.map(File.init(name:))
    ...
}