Skip to content

Instantly share code, notes, and snippets.

@rockbruno
Created April 2, 2020 12:10
Show Gist options
  • Save rockbruno/64b26cb2ecdbec13a31f5f1b315f629f to your computer and use it in GitHub Desktop.
Save rockbruno/64b26cb2ecdbec13a31f5f1b315f629f to your computer and use it in GitHub Desktop.
Modifying immutable structs without var in Swift
protocol ImmutableCopy {
associatedtype InitializerTuple
var lastInitParams: AnyInitializerParams<InitializerTuple> { get }
func copy(from: (InitializerTuple) -> Self, applying: (inout InitializerTuple) -> Void) -> Self
}
extension ImmutableCopy {
func copy(from: (InitializerTuple) -> Self, applying: (inout InitializerTuple) -> Void) -> Self {
var values = lastInitParams.values
applying(&values)
return from(values)
}
}
// This type exists so types that inherit ImmutableCopy can be Equatable/Codable/Hashable and so on
// TODO: Make this type all of that
struct AnyInitializerParams<Tuple> {
let values: Tuple
init(_ values: Tuple) {
self.values = values
}
}
struct MyStruct: ImmutableCopy {
//
typealias InitializerTuple = (a: Int, b: String)
let lastInitParams: AnyInitializerParams<InitializerTuple>
//
let a: Int
let b: String
init(a: Int, b: String) {
self.a = a
self.b = b
self.lastInitParams = AnyInitializerParams((a, b))
}
}
/////////////
let a = MyStruct(a: 1, b: "")
let b = a.copy(from: MyStruct.init(a:b:)) { values in
values.b = "2"
}
dump(a) // MyStruct(a: 1, b: "")
dump(b) // MyStruct(a: 1, b: "2")
////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment