Lens introduction

3925ee6eaa41031bac799de0f4f528ec?s=47 to4iki
February 18, 2018

Lens introduction

in `swift` implementation
see: https://github.com/to4iki/LensKit

3925ee6eaa41031bac799de0f4f528ec?s=128

to4iki

February 18, 2018
Tweet

Transcript

  1. Lens Shinjuku.LT#17 @to4iki 1

  2. Me • Takezawa •  • ! • ☕ •

    ♨ 2
  3. what Lens? 3

  4. Def. / Feature • getter/setterͷந৅Խɾম͖௚͠(൚༻Խ) • ༷ʑͳσʔλΛڞ௨ͷI/FͰૢ࡞Ͱ͖Δ • ಛఆͷݴޠʹґଘ͠ͳ͍֓೦/ܕ •

    functional • ෆมߏ଄ / ߹੒Մೳ • Lens Laws 4
  5. ekmett/lens 5

  6. • Monocle.Lens - elm-monocle • julien-truffaut/Monocle 6

  7. https://github.com/julien-truffaut/Monocle/blob/master/image/class- diagram.png 7

  8. getter setter 8

  9. getter • ΦϒδΣΫτS͔ΒAΛऔΓग़͢ • get: (S) -> A setter •

    ΦϒδΣΫτSͷ೚ҙͷ஋ΛAʹมߋ͢Δ • set: (S, A) -> S == set: (S) -> A -> S 9
  10. ͜ΕΒͷ͍͢͝ getter/setter1Λ ೚ҙͷΦϒδΣΫτͷ ೚ҙͷϝϯόʹద༻͢Δͷ͕ Lens 1 https://qiita.com/to4iki/items/f0cc28e1102cf53be85d 10

  11. ࣮૷ͯ͠ΈΔ 11

  12. struct Lens<S, T> { private let _get: (S) -> T

    private let _set: (S, T) -> S init(get: @escaping (S) -> T, set: @escaping (S, T) -> S) func get(_ source: S) -> T func set(_ source: S, value: T) -> S } 12
  13. ͜Μ͚ͩ 13

  14. struct User { let name: String } let user =

    User(name: "hoge") let nameLens = Lens<User, String>( get: { $0.name }, set: { User(name: $1) } ) nameLens.get(user) // "hoge" nameLens.set("fuga") // User(name:"fuga)" 14
  15. Usecase? 15

  16. ωετͨ͠σʔλͷ͋ΔҰ෦ ͚ͩΛมߋ͍ͨ͠ struct Street { let name: String } struct

    Address { let street: Street } struct Company { let address: Address } struct Employee { let company: Company } let employee = Employee(company: Company(address: Address(street: Street(name: "street")))) 16
  17. ! let updatedEmployee = Employee(company: Company(address: Address(street: Street(name: employee.company.address.street.name.capitalizedString) )

    ) ) 17
  18. Lens͸߹੒Λ࢖͍ɺ ෆมߏ଄Λอͪͳ͕Β ΞΫηεग़དྷΔ 18

  19. struct Lens<S, T> { ... func compose<U>(_ other: Lens<T, U>)

    -> Lens<S, U> { return Lens<S, U>( get: { (source: S) -> U in other.get(self.get((source))) }, set: { (source: S, value: U) -> S in self.set(source, value: other.set(self.get(source), value: value)) } ) } } 19
  20. (operator΋ఆٛ͠ͱ͘) /// Left-to-Right Composition infix operator >>> : MultiplicationPrecedence func

    >>> <S, T, U>(lhs: Lens<S, T>, rhs: Lens<T, U>) -> Lens<S, U> { return lhs.compose(rhs) } 20
  21. Demo 21

  22. ! let nameLens = Lens<Street, String>(get: { $0.name }, set:

    { Street(name: $1) } ) let streetLens = Lens<Address, Street> ... let addressLens = Lens<Company, Address> ... let companyLens = Lens<Employee, Company> ... let lens: Lens<Employee, String> = companyLens >>> addressLens >>> streetLens >>> nameLens let employee = Employee(company: Company(address: Address(street: Street(name: "street")))) let updatedEmployee = lens.modify(employee) { $0.capitalized } // Employee(Company(Address(Street(name: "Street") 22
  23. https://github.com/ to4iki/LensKit 23

  24. Conclusion • Lens ͸ ͍͢͝getter/setter • ෆมߏ଄Λอͪͳ͕Β • ਂ͍ߏ଄Ͱ΋ •

    ஋ʹΞΫηεग़དྷΔ • Ϣʔεέʔε͸ਖ਼௚೉͍͠ • ςετ࣌ͷαϙʔτͱͯ͠࢖͏? 24
  25. See also • ࠓ͔Β࢝ΊΔ Lens/Prism 25