0Pricing
Scala for Backend Engineering & Functional Programming · Lezione

Stream infiniti

Modelli dati senza fine in sicurezza.

Stream infiniti è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.

Infinito, in sicurezza

Una LazyList può descrivere una sequenza infinita perché la coda non viene mai calcolata finché non viene richiesta. Si materializza solo il prefisso che si consuma.

Questo consente di modellare numeri naturali, numeri primi o letture di sensori senza porre un limite in anticipo.

Tutti i numeri naturali

LazyList.from(1) è la sequenza infinita 1, 2, 3, ... È possibile prelevare qualsiasi prefisso finito.

Forzarla interamente non terminerebbe mai, quindi la si limiti sempre con take o la si interrompa con un predicato.

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

from con un passo

LazyList.from(start, step) conta a intervalli regolari. Lo usi per numeri pari, intervalli temporali o qualsiasi progressione aritmetica.

La sequenza è infinita, ma ogni chiamata a take forza solo ciò che viene richiesto.

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

Stream autoreferenziali

Un trucco famoso consiste nel definire una LazyList in termini di se stessa. La sequenza di Fibonacci può essere scritta unendo lo stream alla propria coda.

Funziona solo perché la coda rimane non valutata finché non viene richiesto ciascun elemento.

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 ...

Eseguire Fibonacci

Forziamo un prefisso di quello stream di Fibonacci autoreferenziale.

Ogni nuovo elemento viene calcolato a partire da elementi precedenti già memorizzati, quindi il tutto rimane efficiente man mano che si prelevano altri valori.

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 per le sequenze

LazyList.iterate genera una sequenza infinita tramite una funzione di passaggio. Potenze, crescita geometrica e macchine a stati si adattano naturalmente a questo approccio.

Qui ogni elemento è il triplo del precedente, per sempre.

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

Un setaccio di numeri primi

Gli stream infiniti sono ideali per il crivello di Eratostene. Si prenda un primo in testa, si filtrino i suoi multipli dal resto e si ricorra.

Il filtro è lazy, quindi i numeri primi vengono prodotti uno alla volta man mano che vengono consumati.

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

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

Eseguire il setaccio

Ora preleviamo i primi dieci numeri primi da quel setaccio infinito.

Viene forzata solo la quantità necessaria dello stream numerico sottostante per ottenere dieci numeri primi, dimostrando il calcolo guidato dalla richiesta.

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)
}

Non forzare mai l'intera sequenza

I metodi che richiedono l'intera sequenza, come length, toList su uno stream non limitato o foreach senza un arresto, rimarranno bloccati su una LazyList infinita.

Applichi sempre prima un limite con take, takeWhile o find.

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

La trappola della testa conservata

Se un val conserva la testa di una LazyList infinita memoizzata e la si consuma molto avanti, ogni cella forzata rimane in memoria, causando una perdita di memoria.

Per attraversamenti lunghi, consumi i dati tramite un metodo senza associare la testa a una variabile oppure usi un Iterator.

Perché gli stream infiniti sono importanti

Gli stream infiniti consentono di separare la generazione dal consumo. Il produttore descrive una regola senza fine; il consumatore decide quanto realizzare.

È un potente schema funzionale per pipeline, simulazioni e sorgenti di dati lazy.

Verifica rapida

Verifichi la sua comprensione delle LazyList infinite.

Riepilogo

Le LazyList infinite funzionano perché la coda viene valutata su richiesta: from, iterate, fibs autoreferenziale e il crivello dei numeri primi generano elementi senza fine, ma ne realizzano solo quanti ne vengono consumati.

Eviti le operazioni sull'intera sequenza e il mantenimento della testa. Ora impariamo a prendere e filtrare gli elementi in modo lazy.

Domande Frequenti

La lezione «Stream infiniti» è gratuita?

Sì — il testo completo di «Stream infiniti» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.

Cosa imparerò in «Stream infiniti»?

Modelli dati senza fine in sicurezza. Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?

Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Stream infiniti»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?

Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. La pigrizia spiegata
  2. Costruire una LazyList
  3. Stream infiniti
  4. Prelevare e filtrare in modo lazy
← Torna a Scala for Backend Engineering & Functional Programming