렌즈를 추가하지 않았다는 사실이 재밌습니다. 그래서, 여기 그것에 CS 배경 용지이며, 여기에 렌즈에 터치 간단히 스칼라에서 사용하는 블로그입니다, 여기 Scalaz의 렌즈를 구현하고 여기에 의외로 질문처럼 보이는 그것을 사용하는 일부 코드이다. 그리고, 보일러 판을 줄이기 위해 여기 경우 클래스 Scalaz 렌즈를 생성하는 플러그인은.
보너스 포인트를 들어, 여기에 렌즈에 닿는 또 다른 SO 질문 및 종이 토니 모리스가.
렌즈의 큰 문제는 구성이 가능하다는 것입니다. 따라서 처음에는 약간 번거롭지 만 더 많이 사용할수록 계속해서 자리를 잡습니다. 또한 개별 렌즈를 테스트하기 만하면되고 그 구성을 당연하게 받아 들일 수 있기 때문에 테스트 가능성에 매우 좋습니다.
따라서이 답변의 끝에 제공된 구현을 기반으로 렌즈로 수행하는 방법은 다음과 같습니다. 먼저 렌즈를 신고하여 주소의 우편 번호를 변경하고 사람의 주소를 변경합니다.
val addressZipCodeLens = Lens(
get = (_: Address).zipCode,
set = (addr: Address, zipCode: Int) => addr.copy(zipCode = zipCode))
val personAddressLens = Lens(
get = (_: Person).address,
set = (p: Person, addr: Address) => p.copy(address = addr))
이제 사람의 우편 번호를 변경하는 렌즈를 얻으려면 구성하십시오.
val personZipCodeLens = personAddressLens andThen addressZipCodeLens
마지막으로 해당 렌즈를 사용하여 raj를 변경합니다.
val updatedRaj = personZipCodeLens.set(raj, personZipCodeLens.get(raj) + 1)
또는 몇 가지 구문 설탕을 사용합니다.
val updatedRaj = personZipCodeLens.set(raj, personZipCodeLens(raj) + 1)
또는:
val updatedRaj = personZipCodeLens.mod(raj, zip => zip + 1)
다음은이 예제에 사용 된 Scalaz에서 가져온 간단한 구현입니다.
case class Lens[A,B](get: A => B, set: (A,B) => A) extends Function1[A,B] with Immutable {
def apply(whole: A): B = get(whole)
def updated(whole: A, part: B): A = set(whole, part) // like on immutable maps
def mod(a: A, f: B => B) = set(a, f(this(a)))
def compose[C](that: Lens[C,A]) = Lens[C,B](
c => this(that(c)),
(c, b) => that.mod(c, set(_, b))
)
def andThen[C](that: Lens[B,C]) = that compose this
}