Skip to content

Instantly share code, notes, and snippets.

@jmartinesp
Last active April 4, 2021 20:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jmartinesp/f46452623e44e111f9c343de5ceb0329 to your computer and use it in GitHub Desktop.
Save jmartinesp/f46452623e44e111f9c343de5ceb0329 to your computer and use it in GitHub Desktop.
protocol Copyable {
func copy<V1>(_ keypath1: WritableKeyPath<Self, V1>, _ value1: V1) -> Self
func copy<V1, V2>(_ keypath1: WritableKeyPath<Self, V1>, _ value1: V1, _ keypath2: WritableKeyPath<Self, V2>, _ value2: V2) -> Self
func copy<V1, V2, V3>(_ keypath1: WritableKeyPath<Self, V1>, _ value1: V1,
_ keypath2: WritableKeyPath<Self, V2>, _ value2: V2,
_ keypath3: WritableKeyPath<Self, V3>, _ value3: V3) -> Self
func copy<V1>(_ copiedValue: CopiedValue<Self, V1>) -> Self
func copy<V1, V2>(_ copiedValue: CopiedValue<Self, V1>, _ copiedValue2: CopiedValue<Self, V2>) -> Self
}
typealias CopiedValue<Root, Value> = (keyPath: WritableKeyPath<Root, Value>, value: Value)
extension Copyable {
func copy<V1>(_ keypath1: WritableKeyPath<Self, V1>, _ value1: V1) -> Self {
var copy = self
copy[keyPath: keypath1] = value1
return copy
}
func copy<V1, V2>(_ keypath1: WritableKeyPath<Self, V1>, _ value1: V1, _ keypath2: WritableKeyPath<Self, V2>, _ value2: V2) -> Self {
var copy = self
copy[keyPath: keypath1] = value1
copy[keyPath: keypath2] = value2
return copy
}
func copy<V1, V2, V3>(_ keypath1: WritableKeyPath<Self, V1>, _ value1: V1,
_ keypath2: WritableKeyPath<Self, V2>, _ value2: V2,
_ keypath3: WritableKeyPath<Self, V3>, _ value3: V3) -> Self {
var copy = self
copy[keyPath: keypath1] = value1
copy[keyPath: keypath2] = value2
copy[keyPath: keypath3] = value3
return copy
}
func copy<V1>(_ copiedValue: CopiedValue<Self, V1>) -> Self {
var copy = self
copy[keyPath: copiedValue.keyPath] = copiedValue.value
return copy
}
func copy<V1, V2>(_ copiedValue: CopiedValue<Self, V1>, _ copiedValue2: CopiedValue<Self, V2>) -> Self {
var copy = self
copy[keyPath: copiedValue.keyPath] = copiedValue.value
copy[keyPath: copiedValue2.keyPath] = copiedValue2.value
return copy
}
}
extension WritableKeyPath {
func to(_ value: Value) -> CopiedValue<Root, Value> {
return (keyPath: self, value: value)
}
}
infix operator .=
func .=<Root, Value>(keypath: WritableKeyPath<Root, Value>, value: Value) -> CopiedValue<Root, Value> {
return (keyPath: keypath, value: value)
}
struct SimpleStruct {
var string: String
var int: Int
var optional: Optional<String>
let constant: String
}
extension SimpleStruct: Copyable {}
let simpleStruct = SimpleStruct(string: "a", int: 0, optional: "b", constant: "c")
let modified = simpleStruct.copy(\.string, "test")
let modifiedOptional = simpleStruct.copy(\.optional, nil)
let modifyAll = simpleStruct.copy(\.string, "again",
\.int, -1,
\.optional, "notOptional")
let testWithCopiedValue = simpleStruct.copy((\.string, "a"))
let test = (\SimpleStruct.string).to("a")
let test2 = (\SimpleStruct.string) .= "a"
let testWithCopiedValue2 = simpleStruct.copy(\.string .= "b", \.optional .= nil)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment