Le Lazy Collections (collezioni pigre) sono un meccanismo speciale introdotto in Swift 2 che consente di posticipare i calcoli sulle collezioni fino al momento in cui si accede effettivamente al risultato. Inizialmente, i metodi standard delle collezioni (come map, filter) restituivano il risultato completamente calcolato di una nuova collezione, il che a volte portava a costi non necessari in termini di memoria e tempo, specialmente quando si lavorava con grandi array o catene di trasformazioni.
Problema risiede nella creazione eccessiva di collezioni intermedie. Ogni chiamata a map o filter crea una nuova copia dei dati, il che, in caso di molteplici trasformazioni, riduce notevolmente le prestazioni del programma.
Soluzione: utilizzare collezioni pigre tramite la proprietà .lazy. Swift unisce tutte le operazioni in una catena e calcola solo quegli elementi ai quali ci si riferisce effettivamente.
Esempio di codice:
let array = Array(1...1_000_000) let result = array.lazy.filter { $0 % 2 == 0 }.map { $0 * 3 } print(result.prefix(5)) // Solo i primi 5 valori verranno calcolati
Caratteristiche principali:
Domanda 1: Restituisce let b = a.lazy.map { ... } immediatamente il risultato del calcolo?
No, quando si utilizza .lazy e i metodi map/filter, il risultato del calcolo viene restituito solo al momento di accedere effettivamente ai dati (ad esempio, tramite for-in, first, reduce).
Esempio di codice:
let array = [1, 2, 3] let mapped = array.lazy.map { x in print("processing\(x)") return x * 2 } // A questo punto, nulla verrà stampato let first = mapped.first // Qui inizieranno i calcoli e apparirà l'output
Domanda 2: È possibile aggiungere un nuovo elemento alla collezione originale dopo .lazy e sarà anch'esso elaborato se si accede al risultato in seguito?
No, la Lazy Collection riflette lo stato della collezione al momento della creazione della rappresentazione pigra. Gli elementi aggiunti successivamente non verranno considerati.
Domanda 3: L'uso di .lazy è efficace per piccole collezioni (<100 elementi)?
No, per piccole collezioni il guadagno dalle computazioni pigre è praticamente invisibile, e a volte l'overhead aggiuntivo influisce negativamente sulle prestazioni.
Nel progetto si è utilizzato senza riflessione .lazy per tutti i map/filter anche su piccole collezioni.
Pro:
Contro:
Abbiamo rifattorizzato i report su un grande database di transazioni usando .lazy solo per le funzioni in cui c'erano effettivamente lunghe catene di trasformazioni.
Pro:
Contro: