In the previous section, we covered copy constructors. Here, we will examine a functional structure called a lens. Simply put, lenses are functional getters and setters that are implemented for a whole object and its parts:
- Getters: We can look through the lens at an immutable object to get its parts
- Setters: We can use the lens to change a part of an immutable object
Let's implement a lens:
struct Lens<Whole, Part> {
let get: (Whole) -> Part
let set: (Part, Whole) -> Whole
}
Let's use it to change our FunctionalProduct object to get and set the producer property:
let prodProducerLens: Lens<FunctionalProduct, Producer> =
Lens(get: { $0.producer },
set: {
FunctionalProduct(name: $1.name,
price: $1.price,
quantity: $1.quantity,
producer: $0) })
Let's change the producer for mexBananas:
let mexBananas2 = prodProducerLens.set(Producer(name: "QAZ",
address: "Yucatan,
Mexico"), mexBananas)
Through our lens, we can change it as shown in the preceding code.
Let's examine another example. Suppose that we have a Producer object as follows:
let chineeseProducer = Producer(name: "KGJ",
address: "Beijing, China")
We want to change the address:
let producerAddressLens: Lens<Producer, String> =
Lens(get: {
$0.address },
set: {
Producer(name: $1.name,
address: $0) })
let chineeseProducer2 = producerAddressLens.set("Shanghai, China", chineeseProducer)
Suppose that we had mexBananas2 and needed to have a Chinese banana producer, then we could use:
let chineeseBananaProducer = prodProducerLens.set(producerAddressLens.set("Shanghai, China", chineeseProducer), mexBananas2)
This syntax does not look very simple, and it seems that we did not gain much after all. In the next section, we will simplify it.