Skip to content

Instantly share code, notes, and snippets.

@tLewisII
Last active March 20, 2019 23:17
Show Gist options
  • Save tLewisII/93bbde6ebf2872b34c7560124a06a034 to your computer and use it in GitHub Desktop.
Save tLewisII/93bbde6ebf2872b34c7560124a06a034 to your computer and use it in GitHub Desktop.
KeyPath Lenses
import Foundation
precedencegroup LeftApplyPrecedence {
associativity: left
higherThan: AssignmentPrecedence
lowerThan: TernaryPrecedence
}
precedencegroup FunctionCompositionPrecedence {
associativity: right
higherThan: LeftApplyPrecedence
}
precedencegroup LensSetPrecedence {
associativity: left
higherThan: FunctionCompositionPrecedence
}
infix operator |> : LeftApplyPrecedence
infix operator .~ : LensSetPrecedence
public func |><A,B>(a:A, f:(A) -> B) -> B {
return f(a)
}
public func .~ <Whole, Part> (lens: WritableKeyPath<Whole,Part>, part: Part) -> (Whole) -> Whole {
return { whole in
var copy = whole
copy[keyPath:lens] = part
return copy
}
}
struct User {
private(set) var name:String
private(set) var id:Int
init(id:Int, name:String) {
self.name = name
self.id = id
}
}
let user = User(id: 1, name: "Terry")
let newUser =
user
|> (\User.name) .~ "Bob"
|> (\User.id) .~ 2
dump(user) // Name:"Terry", id:1
dump(newUser) // Name:"Bob", id:2
@eliotfowler
Copy link

This is awesome, thanks! Is there any way to set up the precedence groups so we don't need the parentheses around the keypaths?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment