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) }
}
}