0Pricing
Scala for Backend Engineering & Functional Programming · Lekcja

Nieskończone strumienie

Bezpiecznie zamodeluje Pan/Pani niekończące się dane.

Nieskończone strumienie to bezpłatna lekcja Scala for Backend Engineering & Functional Programming na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Scala for Backend Engineering & Functional Programming, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.

Nieskończoność bezpiecznie

LazyList może opisywać nieskończoną sekwencję, ponieważ jej ogon nie jest obliczany, dopóki nie okaże się potrzebny. Materializowany jest tylko ten początkowy fragment, który zostanie wykorzystany.

Pozwala to modelować liczby naturalne, liczby pierwsze lub odczyty z czujników bez wcześniejszego ustalania ograniczenia.

Wszystkie liczby naturalne

LazyList.from(1) to nieskończona sekwencja 1, 2, 3, ... Można pobrać dowolny skończony początkowy fragment.

Wymuszenie obliczenia całej sekwencji nigdy by się nie zakończyło, dlatego zawsze należy ograniczyć ją za pomocą take lub zakończyć predykatem.

object Demo extends App {
  val nats = LazyList.from(1)
  println(nats.take(5).toList)
}

from z krokiem

LazyList.from(start, step) tworzy ciąg, zwiększając wartość o określony odstęp. Można go użyć dla liczb parzystych, taktów zegara lub dowolnego ciągu arytmetycznego.

Sekwencja jest nieskończona, ale każde wywołanie take wymusza tylko tyle elementów, ile Państwo zażądają.

object Demo extends App {
  val evens = LazyList.from(0, 2)
  println(evens.take(5).toList)
}

Strumienie odwołujące się do samych siebie

Istnieje znana sztuczka: definiowanie LazyList za pomocą niej samej. Ciąg Fibonacciego można zapisać, łącząc strumień z jego własnym ogonem.

Działa to wyłącznie dlatego, że ogon pozostaje nieobliczony do momentu pobrania każdej kolejnej komórki.

lazy val fibs: LazyList[Int] =
  0 #:: 1 #:: fibs.zip(fibs.tail).map { case (a, b) => a + b }
// fibs(0)=0, fibs(1)=1, fibs(2)=1 ...

Uruchamianie ciągu Fibonacciego

Wymuśmy początkowy fragment samoodwołującego się strumienia Fibonacciego.

Każdy nowy element jest obliczany na podstawie wcześniejszych, już zapamiętanych elementów, dzięki czemu całość pozostaje wydajna podczas pobierania kolejnych wartości.

object Demo extends App {
  lazy val fibs: LazyList[Int] =
    0 #:: 1 #:: fibs.zip(fibs.tail).map { case (a, b) => a + b }
  println(fibs.take(10).toList)
}

iterate dla sekwencji

LazyList.iterate generuje nieskończoną sekwencję za pomocą funkcji przejścia. Naturalnie pasuje do potęg, wzrostu geometrycznego i automatów stanów.

W tym przykładzie każdy element jest trzy razy większy od poprzedniego — bez końca.

object Demo extends App {
  val triples = LazyList.iterate(1)(_ * 3)
  println(triples.take(6).toList)
}

Sito liczb pierwszych

Nieskończone strumienie świetnie nadają się do sita Eratostenesa. Należy pobrać pierwszą liczbę pierwszą, odfiltrować jej wielokrotności z pozostałej części i wykonać rekurencję.

Filtrowanie jest leniwe, więc liczby pierwsze są tworzone pojedynczo w miarę ich pobierania.

def sieve(s: LazyList[Int]): LazyList[Int] =
  s.head #:: sieve(s.tail.filter(_ % s.head != 0))

val primes = sieve(LazyList.from(2))

Uruchamianie sita

Pobierzmy teraz pierwszych dziesięć liczb pierwszych z tego nieskończonego sita.

Wymuszona zostanie tylko taka część bazowego strumienia liczb, która wystarczy do uzyskania dziesięciu liczb pierwszych, co pokazuje działanie obliczeń sterowanych zapotrzebowaniem.

object Demo extends App {
  def sieve(s: LazyList[Int]): LazyList[Int] =
    s.head #:: sieve(s.tail.filter(_ % s.head != 0))
  val primes = sieve(LazyList.from(2))
  println(primes.take(10).toList)
}

Nigdy nie wymuszaj całej sekwencji

Metody wymagające całej sekwencji, takie jak length, toList dla nieograniczonego strumienia lub foreach bez warunku zatrzymania, zawieszą się na nieskończonej LazyList.

Najpierw zawsze należy ograniczyć sekwencję za pomocą take, takeWhile lub find.

// DON'T: LazyList.from(1).toList    // hangs forever
val ok = LazyList.from(1).take(3).toList

Pułapka przechowywania głowy

Jeśli val przechowuje głowę nieskończonej, zapamiętującej wartości LazyList, a następnie przejdą Państwo daleko w głąb sekwencji, każda wymuszona komórka pozostanie aktywna, powodując wyciek pamięci.

Podczas długiego przechodzenia po sekwencji należy użyć metody bez przypisywania głowy do zmiennej albo skorzystać z Iterator.

Dlaczego nieskończone strumienie mają znaczenie

Nieskończone strumienie pozwalają oddzielić generowanie od pobierania danych. Producent opisuje nieskończoną regułę, a odbiorca decyduje, jak dużą część zrealizować.

To potężny wzorzec funkcyjny przydatny w potokach, symulacjach i leniwych źródłach danych.

Szybkie sprawdzenie

Proszę sprawdzić swoją wiedzę na temat nieskończonych LazyList.

Podsumowanie

Nieskończone LazyList działają, ponieważ ogon jest sterowany zapotrzebowaniem: from, iterate, samoodwołujący się fibs oraz sito liczb pierwszych generują elementy bez końca, ale realizują tylko te, które zostaną pobrane.

Należy unikać operacji na całej sekwencji i przetrzymywania głowy. Następnie opanujemy leniwe pobieranie i filtrowanie.

Często zadawane pytania

Czy lekcja „Nieskończone strumienie” jest bezpłatna?

Tak — pełny tekst „Nieskończone strumienie” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Scala for Backend Engineering & Functional Programming, przejdź na CoddyKit PRO. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.

Co nauczysz się w „Nieskończone strumienie”?

Bezpiecznie zamodeluje Pan/Pani niekończące się dane. Ćwiczysz Scala for Backend Engineering & Functional Programming z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Scala for Backend Engineering & Functional Programming?

Nie wymagamy żadnego doświadczenia. Scala for Backend Engineering & Functional Programming w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Nieskończone strumienie”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Scala for Backend Engineering & Functional Programming?

Tak. Każda lekcja Scala for Backend Engineering & Functional Programming zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Wyjaśnienie leniwości
  2. Budowanie LazyList
  3. Nieskończone strumienie
  4. Leniwe pobieranie i filtrowanie
← Powrót do Scala for Backend Engineering & Functional Programming