Lazy Collections (leniwe kolekcje) to szczególny mechanizm, który pojawił się w Swift 2 i pozwala na odkładanie obliczeń nad kolekcjami do momentu bezpośredniego odwołania się do wyniku. Początkowo standardowe metody kolekcji (np. map, filter) zwracały w pełni obliczony wynik nowej kolekcji, co czasami prowadziło do niepotrzebnych kosztów pamięci i czasu, szczególnie przy pracy z dużymi tablicami lub łańcuchami transformacji.
Problem polega na nadmiernym tworzeniu pośrednich kolekcji. Każde wywołanie map lub filter tworzy nową kopię danych, co przy wielokrotnych transformacjach znacznie obniża wydajność programu.
Rozwiązanie — używać leniwych kolekcji za pomocą właściwości .lazy. Swift łączy wszystkie operacje w jeden łańcuch i oblicza tylko te elementy, do których naprawdę się odwołują.
Przykład kodu:
let array = Array(1...1_000_000) let result = array.lazy.filter { $0 % 2 == 0 }.map { $0 * 3 } print(result.prefix(5)) // Tylko 5 pierwszych wartości zostanie obliczonych
Kluczowe cechy:
Pytanie 1: Czy let b = a.lazy.map { ... } zwraca od razu wynik obliczenia?
Nie, przy użyciu .lazy i metod map/filter wynik obliczenia jest zwracany tylko przy bezpośrednim odwołaniu do danych (np. przez for-in, first, reduce).
Przykład kodu:
let array = [1, 2, 3] let mapped = array.lazy.map { x in print("przetwarzanie\(x)") return x * 2 } // Na tym etapie nic się nie wyświetli let first = mapped.first // Tutaj rozpoczną się obliczenia i pojawi się wyjście
Pytanie 2: Czy można dodać nowy element do oryginalnej kolekcji po .lazy i zostanie on także przetworzony, jeśli odwołamy się do wyniku później?
Nie, Lazy Collection odzwierciedla stan kolekcji w momencie tworzenia leniwego przedstawienia. Później dodane elementy nie będą brane pod uwagę.
Pytanie 3: Czy użycie .lazy jest efektywne dla małych kolekcji (<100 elementów)?
Nie, dla małych kolekcji korzyści z leniwych obliczeń są praktycznie niewidoczne, a czasami dodatkowy overhead negatywnie wpływa na wydajność.
W projekcie bezmyślnie używano .lazy dla wszystkich map/filter, nawet w małych kolekcjach.
Zalety:
Wady:
Refaktoryzowaliśmy raporty po dużej bazie transakcji, stosując .lazy tylko w funkcjach, gdzie rzeczywiście były długie łańcuchy transformacji.
Zalety:
Wady: