Lens e Prism ci consentono di stabilire una sorta di relazione tra strutture dati, in particolare Lens ci consente di focalizzarci e agire su una parte specifica di tale struttura dati come ad esempio effettuando un “set” o un “get” su tale parte della struttura dati.
Per definire un Lens dal tipo A, che contiene istanze dei tipi B e C abbiamo bisogno di due funzioni:
- una funzione get che ha come input A, tale funzione ci restituirà una B
- una funzione set che, dato B, restituirà una funzione di trasformazione per A, cioè una funzione di tipo (A) -> A.
struct Lens<Whole,Part> { let get: (Whole) -> Part let set: (Part) -> (Whole) -> Whole }
In Swift gia’ abbiamo questo pattern integrato di default ovvero i keypath.
Prism e’ concettualmente molto simile a Lens ma con la differenza che quest’ultimo in Swift e’ rappresentato tramite enum.
Possiamo definire un Prism da D (un enum) a F (il tipo associato a uno dei suoi casi). anche qui abbiamo 2 funzioni:
- una funzione tryGet che ha come input un enum D e cerca di restituire una F, ho ho detto “cerca” perché una F può essere recuperata solo se l’istanza D e’ presente nel caso giusto.
- una funzione inject che data una F possiamo ricostruire completamente una D tramite la funzione case
struct Prism<Whole,Part> { let tryGet: (Whole) -> Part? let inject: (Part) -> Whole }
A questo punto passiamo ad un esempio basilare di prism e lens.
Per prima cosa definiamo Prism e Lens
Dopodiche’ definiamo tramite una struct il nostro model Company (che rappresenta un azienda) quindi poiche’ e’ una struct possiamo utilizzare lens per accedere alla struttura typology
Ora definiamo un enum per il JobStatus
Ecco un esempio d’utilizzo