Skip to content

Instantly share code, notes, and snippets.

@oleksii-demedetskyi
Created June 15, 2019 19:47
Show Gist options
  • Save oleksii-demedetskyi/7f8fb199ec362388ff39791ea4997c16 to your computer and use it in GitHub Desktop.
Save oleksii-demedetskyi/7f8fb199ec362388ff39791ea4997c16 to your computer and use it in GitHub Desktop.
Allows updates even to let constants and tracking of updates
import Cocoa
protocol Primitive {}
extension Int: Primitive {}
@dynamicMemberLookup
struct Draft<Value> {
let value: Value
var updates: [PartialKeyPath<Value>: Any] = [:]
subscript<T>(dynamicMember keyPath: KeyPath<Value, T>) -> T where T: Primitive {
get {
guard
let someResult = updates[keyPath],
let result = someResult as? T else {
return value[keyPath: keyPath]
}
return result
}
mutating set {
updates[keyPath] = newValue
}
}
subscript<T>(dynamicMember keyPath: KeyPath<Value, T>) -> Draft<T> {
get {
guard
let someResult = updates[keyPath],
let result = someResult as? Draft<T> else {
return Draft<T>(value: value[keyPath: keyPath])
}
return result
}
mutating set {
updates[keyPath] = newValue
}
}
}
struct CounterPair {
let left: Int
let right: Int
}
struct App {
let first: CounterPair
let second: CounterPair
}
let app = App(
first: CounterPair(left: 10, right: 20),
second: CounterPair(left: 30, right: 40))
var appDraft = Draft(value: app)
print(appDraft.first.left) // 10
appDraft.first.left += 1
print(appDraft.first.left) // 11
print(appDraft.updates)
// [KeyPath<App, CounterPair>: Draft<CounterPair>(
// value: CounterPair(left: 10, right: 20),
// updates: [KeyPath<CounterPair, Int>: 11]
// )]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment