Introducing swift-dependencies, a dependency injection library inspired by SwiftUI's "environment"

On the occasions where I’ve really, really wanted a generic function as a value, what I’ve ended up with is a protocol and struct combo:

protocol ThingConsumer {
    func callAsFunction<T: Thing>(_ value: T)
}

struct ConcreteThingConsumer: ThingConsumer {
    func callAsFunction<T: Thing>(_ value: T) {
        ...
    }
}

In your case, I’d be tempted to go with a single protocol, but using two pseudo-functions also works (and even gives you argument labels back):

protocol SettingsGetter {
    func callAsFunction<T:Codable>(_ setting: Setting) -> T
}

protocol SettingsSetter {
    func callAsFunction<T:Codable>(_ setting: Setting, to value: T)
}

struct Settings {
    var get: SettingsGetter
    var set: SettingsSetter

    public var locale: Locale {
        get { get(.locale) }
        nonmutating set { set(.locale, to: newValue) }
    }
}
2 Likes