Skip to content

Instantly share code, notes, and snippets.

@romdevios
Last active October 21, 2023 09:10
Show Gist options
  • Save romdevios/752d59b1fa5e1097cd9687880bcc13c6 to your computer and use it in GitHub Desktop.
Save romdevios/752d59b1fa5e1097cd9687880bcc13c6 to your computer and use it in GitHub Desktop.
This struct can store flexible amount of parameters that will be type safe to use.
import Foundation
@dynamicMemberLookup
struct DynamicParameterStore<Holder, Wrapped> {
private let holder: Holder
private let wrapped: Wrapped
subscript<Value>(dynamicMember keyPath: KeyPath<Holder, Value>) -> Value {
holder[keyPath: keyPath]
}
subscript<Value>(dynamicMember keyPath: KeyPath<Wrapped, Value>) -> Value {
wrapped[keyPath: keyPath]
}
}
extension DynamicParameterStore where Wrapped == Void {
init(holder: Holder) {
self.init(holder: holder, wrapped: ())
}
}
extension DynamicParameterStore {
func appending<H>(parameter: H) -> DynamicParameterStore<H, Self> {
DynamicParameterStore<H, Self>(holder: parameter, wrapped: self)
}
}
// MARK: - example parameter holders
struct IntParameterHolder {
let intParameter: Int // name of this parameter will give you access to its value in dynamicStore
}
struct OtherIntParameterHolder {
let otherIntParameter: Int
}
struct StringParameterHolder {
let stringParameter: String
}
// MARK: - store creation
let dynamicStorage = DynamicParameterStore(holder: IntParameterHolder(intParameter: 1))
.appending(parameter: OtherIntParameterHolder(otherIntParameter: 2))
.appending(parameter: StringParameterHolder(stringParameter: "123"))
.appending(parameter: StringParameterHolder(stringParameter: "456")) // this replacing previous parameter value
.appending(parameter: OtherIntParameterHolder(otherIntParameter: 3)) // this will replace second parameter value
// MARK: - stored parameters usage
print(
dynamicStorage.intParameter, // you can call any of placed parameter
dynamicStorage.otherIntParameter,
dynamicStorage.stringParameter
)
/// prints:`1` `3` `456`
/// be careful with repeating holder usage
// type of dynamicStorage is:
/// DynamicParameterStore<
/// OtherIntParameterHolder,
/// DynamicParameterStore<
/// StringParameterHolder,
/// DynamicParameterStore<
/// StringParameterHolder,
/// DynamicParameterStore<
/// OtherIntParameterHolder,
/// DynamicParameterStore<
/// IntParameterHolder,
/// Void
/// >
/// >
/// >
/// >
/// >
// MARK: - You can make it mutable, if you want
@dynamicMemberLookup
struct DynamicMutableParameterStore<Holder, Wrapped> {
private var holder: Holder
private var wrapped: Wrapped
subscript<Value>(dynamicMember keyPath: WritableKeyPath<Holder, Value>) -> Value {
get {
holder[keyPath: keyPath]
}
set {
holder[keyPath: keyPath] = newValue
}
}
subscript<Value>(dynamicMember keyPath: WritableKeyPath<Wrapped, Value>) -> Value {
get {
wrapped[keyPath: keyPath]
}
set {
wrapped[keyPath: keyPath] = newValue
}
}
}
extension DynamicMutableParameterStore where Wrapped == Void {
init(holder: Holder) {
self.init(holder: holder, wrapped: ())
}
}
extension DynamicMutableParameterStore {
func appending<H>(parameter: H) -> DynamicMutableParameterStore<H, Self> {
DynamicMutableParameterStore<H, Self>(holder: parameter, wrapped: self)
}
}
struct MutableIntParameterHolder {
var intParameter: Int
}
struct MutableOtherIntParameterHolder {
var otherIntParameter: Int
}
struct MutableStringParameterHolder {
var stringParameter: String
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment