Thật buồn cười là không ai thêm ống kính, vì họ đã MADE cho loại công cụ này. Vì vậy, đây là một bài viết nền CS về nó, đây là một blog chạm nhanh vào các ống kính sử dụng trong Scala, đây là một triển khai ống kính cho Scalaz và đây là một số mã sử dụng nó, trông giống như câu hỏi của bạn. Và, để cắt giảm tấm nồi hơi, đây là một plugin tạo ống kính Scalaz cho các lớp tình huống.
Để nhận điểm thưởng, đây là một câu hỏi SO khác chạm vào ống kính và một bài báo của Tony Morris.
Vấn đề lớn về ống kính là chúng có thể ghép lại được. Vì vậy, ban đầu chúng hơi cồng kềnh, nhưng chúng tiếp tục đạt được nhiều điểm hơn khi bạn sử dụng chúng. Ngoài ra, chúng rất tốt cho khả năng kiểm tra, vì bạn chỉ cần kiểm tra từng ống kính riêng lẻ và có thể được cấp thành phần của chúng.
Vì vậy, dựa trên việc triển khai được cung cấp ở cuối câu trả lời này, đây là cách bạn thực hiện với ống kính. Đầu tiên, khai báo các ống kính để thay đổi mã zip trong một địa chỉ và một địa chỉ trong một người:
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))
Bây giờ, hãy soạn chúng để có một ống kính thay đổi mã zip ở một người:
val personZipCodeLens = personAddressLens andThen addressZipCodeLens
Cuối cùng, sử dụng ống kính đó để thay đổi raj:
val updatedRaj = personZipCodeLens.set(raj, personZipCodeLens.get(raj) + 1)
Hoặc, sử dụng một số đường cú pháp:
val updatedRaj = personZipCodeLens.set(raj, personZipCodeLens(raj) + 1)
Hoặc thậm chí:
val updatedRaj = personZipCodeLens.mod(raj, zip => zip + 1)
Đây là cách thực hiện đơn giản, được lấy từ Scalaz, được sử dụng cho ví dụ này:
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
}