Skip to content

Instantly share code, notes, and snippets.

@damianesteban
Last active April 23, 2017 18:19
Show Gist options
  • Save damianesteban/d1b263462a1e83ba39bd3ca6a060cf12 to your computer and use it in GitHub Desktop.
Save damianesteban/d1b263462a1e83ba39bd3ca6a060cf12 to your computer and use it in GitHub Desktop.
Example of a simple lens in Swift 3
// Concepts based on an excellent article by Maciej Konieczny.
// http://narf.pl/posts/lenses-in-swift
struct ComicBook {
let title: String
let issueNumber: Int
let publisher: Publisher
}
struct Publisher {
let name: String
let address: String
}
// A simple Lens - “functional getters and setters”
struct Lens<Whole, Part> {
let get: (Whole) -> Part
let set: (Part, Whole) -> Whole
}
// Publisher Lens
let comicPublisherLens: Lens<ComicBook, Publisher> =
Lens(get: { $0.publisher },
set: { ComicBook(title: $1.title, issueNumber: $1.issueNumber, publisher: $0) })
// Publisher Address Lens
let publisherAddressLens: Lens<Publisher, String> =
Lens(get: { $0.address },
set: { Publisher(name: $1.name, address: $0) })
let publisher = Publisher(name: "DC", address: "123 Main St., New York, NY")
let comicBook = ComicBook(title: "Action Comics", issueNumber: 1, publisher: publisher)
// Lens Composition
infix operator >>> { associativity right precedence 100 }
func >>><A, B, C>(lhs: Lens<A, B>, rhs: Lens<B, C>) -> Lens<A, C> {
return Lens(get: { rhs.get(lhs.get($0)) },
set: { (c, a) in
lhs.set(rhs.set(c, lhs.get(a)), a)
})
}
// The ComicBook's Publisher moved!
let comicBookPublisherAddress = comicPublisherLens >>> publisherAddressLens
let currentComicBookPublisherAddress = comicBookPublisherAddress.get(comicBook)
let newComicBookPublisherAddress = comicBookPublisherAddress.set("456 Main Ave, Los Angeles, C.A", comicBook)
print(newComicBookPublisherAddress) // ComicBook(title: "Action Comics", issueNumber: 1, publisher: Publisher(name: "DC", address: "456 Main Ave, Los Angeles, C.A"))
@damianesteban
Copy link
Author

Basic example of a Lens in Swift 3.

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