Last active
November 29, 2017 22:54
-
-
Save priteshshah1983/a95e378f82b94614767bbfe0895ae4ac to your computer and use it in GitHub Desktop.
Lenses - Re-imagined with Swift 4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Motivation: | |
// http://chris.eidhof.nl/post/lenses-in-swift/ | |
// https://www.youtube.com/watch?v=ofjehH9f-CU&feature=youtu.be | |
protocol Changeable { | |
func changed<A>(changes: [KeyPath<Self, A>: A]) -> Self | |
} | |
extension Changeable { | |
func changed<A>(changes: [KeyPath<Self, A>: A]) -> Self { | |
var modified = self | |
changes.forEach { readOnlyKeyPath, newValue in | |
// Will this continue to work or is this a bug in the compiler? | |
// https://bugs.swift.org/browse/SR-6502 | |
guard let writeableKeyPath = readOnlyKeyPath as? WritableKeyPath<Self, A> else { return } | |
modified[keyPath: writeableKeyPath] = newValue | |
} | |
return modified | |
} | |
} | |
struct User: Changeable { | |
let firstName: String | |
let lastName: String | |
let age: Int | |
let someInt: Int | |
let address: Address | |
} | |
struct Address: Changeable { | |
let street: String | |
let zipCode: String | |
} | |
let oneMarketStreet = Address(street: "1 Market Street", zipCode: "94105") | |
let jane = User(firstName: "Jane", lastName: "Doe", age: 35, someInt: 123, address: oneMarketStreet) | |
let john = jane.changed(changes: [\.firstName: "John", \.lastName: "Poe"]) | |
.changed(changes: [\.age: 40]) | |
.changed(changes: [\.address.zipCode: "94103"]) | |
print(jane) // User(firstName: "Jane", lastName: "Doe", age: 35, someInt: 123, address: __lldb_expr_244.Address(street: "1 Market Street", zipCode: "94105")) | |
print(john) // User(firstName: "John", lastName: "Poe", age: 40, someInt: 123, address: __lldb_expr_244.Address(street: "1 Market Street", zipCode: "94103")) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment