Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SwiftでLens

matuyuji
February 25, 2016

 SwiftでLens

SwiftでLensを実装する概要と、Lensを自動生成するSwift-IDLの紹介

matuyuji

February 25, 2016
Tweet

More Decks by matuyuji

Other Decks in Programming

Transcript

  1. -FOT struct Lens<Whole, Part> { let get: Whole -> Part

    let set: (Whole, Part) -> Whole } ෆมͳߏ଄ମ΁ͷࢀরɾมߋΛ؆୯ʹ͢Δ΋ͷ
  2. struct Lens<Whole, Part> { let get: Whole -> Part let

    set: (Whole, Part) -> Whole } let p = Person(name: “Yamamoto", address: Address(city: "Osaka")) struct Person { let name: String let address: Address } struct Address { let city: String } let name = Lens<Person, String>( get: { $0.name }, set: { Person(name: $1, address: $0.address) } ) name.get(p) // => “Yamamoto” name.set(p, “Nakayama") // => Person(Nakayama, Osaka)
  3. let p = Person(name: “Yamamoto", address: Address(city: "Osaka")) let name

    = Lens<Person, String>( get: { $0.name }, set: { Person(name: $1, address: $0.address) } ) let address = Lens<Person, Address>( get: { $0.address }, set: { Person(name: $0.name, address: $1) } ) let city = Lens<Address, String>( get: { $0.city }, set: { Address(city: $1) } ) let composed = address.compose(city) composed.get(p) // "Osaka" composed.set(p, "Tokyo") // Person(Yamamoto, Tokyo)
  4. $PNQPTF func compose<Sub>(other: Lens<Part, Sub>) -> Lens<Whole, Sub> { return

    Lens<Whole, Sub>( get: { other.get(self.get($0)) }, set: { obj, newValue in return self.set(obj, other.set(self.get(obj), newValue)) } ) } struct Lens<Whole, Part> { let get: Whole -> Part let set: (Whole, Part) -> Whole }
  5. let newValue = SomeStruct(issuesUrl: oldValue.issuesUrl, hasWiki: oldValue.hasWiki, forksUrl: oldValue.forksUrl, mirrorUrl:

    oldValue.mirrorUrl, subscriptionUrl: oldValue.subscriptionUrl, sshUrl: oldValue.sshUrl, collaboratorsUrl: oldValue.collaboratorsUrl, updatedAt: oldValue.updatedAt, pullsUrl: oldValue.pullsUrl, fullName: newName, issueCommentUrl: oldValue.issueCommentUrl, statusesUrl: oldValue.statusesUrl, id: oldValue.id, keysUrl: oldValue.keysUrl, size: oldValue.size, tagsUrl: oldValue.tagsUrl, issueEventsUrl: oldValue.issueEventsUrl, downloadsUrl: oldValue.downloadsUrl, assigneesUrl: oldValue.assigneesUrl, contentsUrl: oldValue.contentsUrl, hasPages: oldValue.hasPages, gitRefsUrl: oldValue.gitRefsUrl, score: oldValue.score, cloneUrl: oldValue.cloneUrl, watchersCount: oldValue.watchersCount, gitTagsUrl: oldValue.gitTagsUrl, milestonesUrl: oldValue.milestonesUrl, stargazersCount: oldValue.stargazersCount, homepage: oldValue.homepage, branchesUrl: oldValue.branchesUrl, fork: oldValue.fork, commitsUrl: oldValue.commitsUrl, releasesUrl: oldValue.releasesUrl, description: oldValue.description, hasDownloads: oldValue.hasDownloads, labelsUrl: oldValue.labelsUrl, eventsUrl: oldValue.eventsUrl, contributorsUrl: oldValue.contributorsUrl, htmlUrl: oldValue.htmlUrl, forks: oldValue.forks, compareUrl: oldValue.compareUrl, treesUrl: oldValue.treesUrl, watchers: oldValue.watchers, svnUrl: oldValue.svnUrl, forksCount: oldValue.forksCount, mergesUrl: oldValue.mergesUrl, hasIssues: oldValue.hasIssues, blobsUrl: oldValue.blobsUrl, languagesUrl: oldValue.languagesUrl, notificationsUrl: oldValue.notificationsUrl, hooksUrl: oldValue.hooksUrl, openIssuesCount: oldValue.openIssuesCount, commentsUrl: oldValue.commentsUrl, name: oldValue.name, language: oldValue.languagesUrl, url: oldValue.url, createdAt: oldValue.createdAt, archiveUrl: oldValue.archiveUrl, pushedAt: oldValue.pushedAt, defaultBranch: oldValue.defaultBranch, teamsUrl: oldValue.teamsUrl, openIssues: oldValue.openIssues, gitCommitsUrl: oldValue.gitCommitsUrl, subscribersUrl: oldValue.subscribersUrl, stargazersUrl: oldValue.stargazersUrl, gitUrl: oldValue.gitUrl)
  6. let name = Lens<Person, String>( get: { $0.name }, set:

    { Person(name: $1, address: $0.address) } ) let address = Lens<Person, Address>( get: { $0.address }, set: { Person(name: $0.name, address: $1) } ) let city = Lens<Address, String>( get: { $0.city }, set: { Address(city: $1) } )
  7. struct Person: Lensy { let name: String let address: Address

    } struct Address: Lensy { let city: String } swift_idl public struct Person { public let name: String public let address: Address public struct Lenses { public static let name = Lens<Person, String>( g: { $0.name }, s: { (this, newValue) in Person(name: newValue, address: this.address) } ) public static let address = Lens<Person, Address>( g: { $0.address }, s: { (this, newValue) in Person(name: this.name, address: newValue) } ) } public static var $: PersonLensHelper<Person> { return PersonLensHelper<Person>(lens: createIdentityLens()) } } public struct PersonLensHelper<Whole>: LensHelperType { public typealias Part = Person public let lens: Lens<Whole, Part> public init(lens: Lens<Whole, Part>) { self.init(lens: lens) } public var name: LensHelper<Whole, String> { return LensHelper<Whole, String>(parent: self, lens: Person.Lenses.name) } public var address: AddressLensHelper<Whole> { return AddressLensHelper<Whole>(parent: self, lens: Person.Lenses.address) } } public struct Address { public let city: String public struct Lenses { public static let city = Lens<Address, String>( g: { $0.city }, s: { (this, newValue) in Address(city: newValue) } ) } public static var $: AddressLensHelper<Address> { return AddressLensHelper<Address>(lens: createIdentityLens()) } } public struct AddressLensHelper<Whole>: LensHelperType { public typealias Part = Address public let lens: Lens<Whole, Part> public init(lens: Lens<Whole, Part>) { self.init(lens: lens) } public var city: LensHelper<Whole, String> { return LensHelper<Whole, String>(parent: self, lens: Address.Lenses.city) } }
  8. TBGY-FOTZ protocol LensType { typealias Whole typealias Part var get:

    Whole -> LensResult<Part> { get } var set: (Whole, Part) -> LensResult<Whole> { get } } enum LensResult<Element> { case OK(Element) case Error(LensErrorType) }